58th Cygnus<->FSF merge
authorMike Stump <mrs@gcc.gnu.org>
Wed, 15 Mar 1995 23:03:59 +0000 (23:03 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Wed, 15 Mar 1995 23:03:59 +0000 (23:03 +0000)
From-SVN: r9186

18 files changed:
gcc/cp/ChangeLog
gcc/cp/Makefile.in
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c

index 0cbb5de182119d3da0ea99c0a212343b2b27e533..aa13e96d2062aba453a590d36bdc34b0ea89f07b 100644 (file)
@@ -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  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (get_member_function_from_ptrfunc): Save the instance
+       argument, and tack it onto the front of the COND_EXPR to make the
+       semantics come out right.  Grab the instance argument from
+       '*instance_ptrptr', rather than having it passed in separately.
+       
+       * various: Change various consed-up comparison operations to have
+       boolean type.  Remove the instance argument in calls to
+       get_member_function_from_ptrfunc.
+
+       * error.c (dump_expr): Dump true and false as "true" and "false".
+
+       * decl2.c (finish_file): Also set DECL_STATIC_FUNCTION_P on the
+       global init function.
+
+       * decl.c (finish_function): Only set DECL_EXTERNAL here if the
+       inline function is public.
+
+Sat Mar 11 00:58:03 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * init.c (is_friend): Be more careful about checking
+       DECL_CLASS_CONTEXT on non-member functions.
+
+       * decl2.c (finish_vtable_vardecl): Don't bother calling
+       assemble_external here.
+       (prune_vtable_vardecl): New function that just splices out the
+       vtable decl from the top-level decls.
+       (import_export_inline): Unset DECL_EXTERNAL at first.
+       (finish_file): Don't bother calling assemble_external here.  Do
+       splice out all of the vtables.
+
+Fri Mar 10 14:42:29 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (finish_function): If we're not emitting the function yet,
+       call assemble_external for it.
+
+       * decl2.c (finish_prevtable_vardecl): Don't call mark_vtable_entries
+       here.
+       (finish_vtable_vardecl): Don't do the linkage deduction thing here.
+       Also don't splice out the current vtable if it is unused.
+       (finish_file): Move the second walk_vtables and the synthesis check
+       inside the 'reconsider' loop.  Move thunk emission after the
+       'reconsider' loop.
+
+Thu Mar  9 16:28:16 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * pt.c (tsubst): Don't bother calling cp_build_type_variant, since it
+       was passing bogus values for readonly and volatile from the original
+       template decl, not the resultant type of the tsubst call.
+
+       * class.c (duplicate_tag_error): Use cp_error_at to point out the
+       previous definition of the tag.
+
+Thu Mar  9 10:46:17 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (start_function): Clear base_init_insns and protect_list.
+       (struct cp_function): Add base_init_insns field.
+       (push_cp_function_context): Also save base_init_insns.
+       (pop_cp_function_context): Also restore base_init_insns.
+
+Wed Mar  8 13:31:44 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * init.c (member_init_ok_or_else): Check for initializing a static
+       member here.
+       (emit_base_init): Instead of here.
+
+Tue Mar  7 16:03:26 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (build_method_call): Disable synthesis as needed.
+       * lex.c (cons_up_default_function): Ditto.
+
 Tue Mar  7 10:14:29 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
 
        * parse.y: New rules to allow attributes in a prefix position.
@@ -10,6 +87,234 @@ Tue Mar  7 10:14:29 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
        (grokdeclarator): Added code to support machine attributes.
        * Makefile.in (stamp-parse): Expect 5 shift/reduce failures.
 
+Mon Mar  6 15:07:02 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (build_method_call): Don't synthesize methods outside of a
+       function.
+
+       Make base initialization more re-entrant so that synthesis on the
+       fly will work (and, eventually, template instantation on the fly).
+       * init.c (sort_member_init): Don't bother with members that can't be
+       initialized.  Reorganize a bit.  Don't initialize base members here.
+       (sort_base_init): New function, like sort_member_init, but for base
+       classes.  Steals some code from emit_base_init.
+       (emit_base_init): Simplify.  Call sort_{member,base}_init before
+       doing any initialization, so we don't have to save
+       current_{member,base}_init_list in push_cp_function_context.
+       (expand_aggr_vbase_init_1): Adjust for sort_base_init.
+       (expand_aggr_vbase_init): Simplify.
+       * decl.c (struct cp_function): Add protect_list field.
+       (push_cp_function_context): Also save protect_list.
+       (pop_cp_function_context): Also restore protect_list.
+       * call.c (build_method_call): Enable synthesis at point of call.
+       * lex.c (cons_up_default_function): Ditto.
+
+       * parse.y: Turn -ansi checks back into -pedantic checks.
+
+       * init.c (build_new): Fix -fcheck-new for array new.
+
+Sat Mar  4 15:55:42 1995  Fergus Henderson  <fjh@cs.mu.oz.au>
+
+       * typeck.c (build_compound_expr): warn if left-hand operand of
+       comma expression has no side-effects.
+
+Fri Mar  3 15:16:45 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * parse.y (primary): Change 'object qualified_id *' rules to 'object
+       overqualified_id *'.
+
+Fri Mar  3 12:48:17 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * parse.y (unary_expr): Catch doing sizeof an overloaded function.
+       Make the error look the same as the one we issue in c_sizeof.
+
+       * typeck.c (build_binary_op_nodefault): Give an error for trying
+       to compare a pointer-to-member to `void *'.
+
+Fri Mar  3 11:28:50 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (build_unary_op): Handle bool increment with smoke and
+       mirrors here, rather than in expand_increment where it belongs,
+       because Kenner doesn't agree with me.
+
+Fri Mar  3 00:08:10 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * decl.c (grokparms): Catch a PARM_DECL being used for a default
+       argument as well.
+
+Thu Mar  2 20:05:54 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * init.c (build_new): Don't allow new on a function type.
+
+       * parse.y (primary): Avoid a crash when seeing if the arg is of
+       the same type as that given for the typespec in an explicit dtor call.
+
+Thu Mar  2 00:49:38 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (finish_function): Change test for calling
+       mark_inline_for_output.
+
+Wed Mar  1 11:23:46 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (build_modify_expr): Complain if
+       build_default_binary_type_conversion fails.
+
+       * init.c (expand_default_init): Handle arguments of unknown type
+       properly.
+
+       * cvt.c (build_expr_type_conversion): Only complain about ambiguity
+       if 'complain'.
+       * various: Pass 'complain'.
+
+       * typeck.c (comptypes): Be more picky about comparing UPTs.
+
+Wed Mar  1 11:03:41 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * decl.c (grokdeclarator): If declarator is null, say that the
+       type used has an incomplete type.
+
+Wed Mar  1 10:06:20 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * pt.c (instantiate_template): Copy the template arguments to the
+       permanent_obstack.  Also use simple_cst_equal to compare them when
+       looking for a previous instantiation.
+
+       * tree.c (make_deep_copy): Support copying INTEGER_TYPEs (assuming
+       they are array domain types).
+
+Tue Feb 28 23:24:55 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * cp-tree.h: Define WANT_* constants for passing to
+       build_expr_type_conversion.
+       * cvt.c (build_expr_type_conversion): New function to build
+       conversion to one of a group of suitable types.
+       (build_default_binary_type_conversion): Use it.
+       * decl2.c (grok_array_decl): Ditto.
+       * typeck.c (build_unary_op): Ditto.
+       (build_array_ref): Tidy up a bit.
+       (build_binary_op): Ditto.
+
+Tue Feb 28 19:57:31 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * decl.c (grokdeclarator): Don't allow decl of an argument as `void'.
+
+Tue Feb 28 17:23:36 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * parse.y (typed_declspecs1): Add 'typespec reserved_typespecquals
+       reserved_declspecs' rule.
+
+       * parse.y (expr_or_declarator): Remove notype_qualified_id rule.
+       (direct_notype_declarator): Ditto.
+       (complex_direct_notype_declarator): Add notype_qualified_id rule.
+
+       * lex.c (real_yylex): Handle :> digraph properly.
+
+Tue Feb 28 12:26:29 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * decl.c (grokdeclarator): Check if it's a friend, not if it's
+       non-virtual, that's being initialized.  Move the check up to
+       before FRIENDP would get cleared.  Catch an unnamed var/field
+       being declared void.  Say just `field' instead of `structure field'
+       in the error message.  Only go for the operator name if DECLARATOR
+       is non-null.
+
+Tue Feb 28 00:08:01 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (start_function): Complain about abstract return type.
+       (grokdeclarator): Complain about declaring constructors and
+       destructors to be const or volatile.  Complain about declaring
+       destructors to be static.
+
+       * pt.c (uses_template_parms): Handle pmfs.
+
+       * decl.c (grokdeclarator): Don't call variable_size for array bounds
+       that only depend on template constant parameters.
+
+Mon Feb 27 15:38:16 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * error.c (dump_decl): Only look to see if it's a vtable if we
+       actually have a name to check out.
+
+Mon Feb 27 13:37:53 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * cvt.c (convert_to_aggr): Lose misleading shortcut.
+
+Sun Feb 26 17:27:32 1995  Doug Evans  <dje@canuck.cygnus.com>
+
+       * decl.c (set_nested_typename): Always set DECL_IGNORED_P,
+       not just for dwarf.
+
+Sun Feb 26 00:10:18 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * decl.c (grokdeclarator): Don't allow a static member to be
+       declared `register'.
+
+       * init.c (make_friend_class): Move up to a pedwarn for the warning
+       about a class declaring friends with itself.
+
+       * decl.c (grokdeclarator): You can't do `volatile friend class foo'
+       or `inline friend class foo'.  Only try to make a friend out of
+       TYPE if we didn't already reset it to integer_type_node.
+
+Sat Feb 25 22:32:03 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * decl.c (grokdeclarator): Don't allow initialization of a
+       non-virtual function.
+
+       * decl.c (start_function): Do a pedwarn if we're changing `main'
+       to have an int return type.
+
+Sat Feb 25 00:02:05 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (build_modify_expr): Handle simple assignment from
+       TARGET_EXPRs by building up an RTL_EXPR to force expansion.  Whew.
+
+Fri Feb 24 18:27:14 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * decl.c (grokdeclarator): Also don't allow virtual outside of a
+       class decl for a scope method definition performed at global binding.
+
+       * init.c (build_offset_ref): Don't allow creation of an OFFSET_REF
+       of a bitfield.
+
+       * decl.c (grokdeclarator): Don't allow a const to be declared mutable.
+
+       * typeck.c (build_binary_op): Return an error_mark_node if either
+       one of the args turned into an error_mark_node when we tried to
+       use default_conversion.
+
+       * typeck.c (build_unary_op): Forbid using postfix -- on a bool.
+
+       * decl.c (grokdeclarator): Allow `signed' and `unsigned' to be
+       used on `__wchar_t'.
+
+Fri Feb 24 13:59:53 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (end_protect_partials): Do it the right way.
+
+Wed Feb 22 15:42:56 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (build_binary_op_nodefault): Upgrade warning about
+       comparing distinct pointer types to pedwarn.
+
+       * typeck2.c (digest_init): Cope with extra braces.
+
+       * typeck.c (build_binary_op_nodefault): Use tree_int_cst_sgn instead
+       of INT_CST_LT (..., interger_zero_node).
+
+Wed Feb 22 14:45:52 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * except.c [!TRY_NEW_EH] (end_protect_partials): Define dummy
+       function for systems that don't have EH.
+
+Tue Feb 21 19:18:31 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (can_convert_arg): Like can_convert, but takes an arg as
+       well.
+
+       * pt.c (type_unification): Allow implicit conversions for parameters
+       that do not depend on template parameters.
+
 Tue Feb 21 18:43:48 1995  Douglas Rupp  (drupp@cs.washington.edu)
 
        * Make-lang.in, config-lang.in: ($exeext): New macro.
@@ -19,17 +324,46 @@ Tue Feb 21 18:43:48 1995  Douglas Rupp  (drupp@cs.washington.edu)
        * cp/g++.c: Added #ifdefs for sys/file.h and process.h for NT.
        Modified spawnvp to have to correct number of arguments for OS/2, NT.
 
-Thu Feb  2 15:07:58 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+Tue Feb 21 18:36:55 1995  Mike Stump  <mrs@cygnus.com>
+
+       * decl.c (finish_function): Add calls to end_protect_partials to end
+       the exception region that protects constructors so that partially
+       constructed objects can be partially destructed when the constructor
+       throws an exception.
+       * init.c (perform_member_init, sort_member_init, emit_base_init):
+       Added support for partially constructed objects.
+       * init.c (build_partial_cleanup_for): New routine to do partial
+       cleanups of a base class.
+       * decl2.c (finish_file): Move the emitting of the exception table
+       down, after we emit all code that might have exception regions in
+       them.
+       * except.c (end_protect_partials, might_have_exceptions_p): New
+       routines.
+       (emit_exception_table): Always output table if called.
+       * cp-tree.h (protect_list, end_protect_partials,
+       might_have_exceptions_p, emit_exception_table): Added.
+
+Tue Feb 21 16:05:59 1995  Brendan Kehoe  (brendan@lisa.cygnus.com)
+
+       * gc.c (build_typeid): Pass a NULL_TREE, not the bogus, unused
+       address of a local variable.
+       * class.c (build_vfn_ref): Only try to build the PLUS_EXPR if we
+       were given a non-null PTR_TO_INSTPTR.
+
+Tue Feb 21 01:53:18 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (duplicate_decls): Always lay out the merged decl.
+
+       * decl2.c (finish_vtable_vardecl): Don't do vtable hack on templates.
+       (finish_prevtable_vardecl): Ditto.
 
-        * class.c (build_vbase_path): Bash types to make the backend happy.
-        * cvt.c (build_up_reference): Bash the types bashed by
-        build_vbase_path to be reference types instead of pointer types.
-        (convert_to_reference): Ditto.
+       * method.c (synthesize_method): Set interface_{unknown,only}
+       according to the settings for our class, not the file where it comes
+       from.
 
-Wed Jan 25 15:02:09 1995  David S. Miller  (davem@nadzieja.rutgers.edu)
+Sat Feb 18 12:26:48 1995  Mike Stump  <mrs@cygnus.com>
 
-       * class.c (instantiate_type): Change error message text.
-       * typeck2.c (store_init_value): Likewise.
+       * except.c: Handle systems that define __i386__ but not __i386.
 
 Fri Feb 17 15:31:31 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
@@ -518,6 +852,11 @@ Tue Jan 24 16:36:31 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
        * typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR
        will suffice to convert from integer_zero_node.
 
+Wed Jan 25 15:02:09 1995  David S. Miller  (davem@nadzieja.rutgers.edu)
+
+       * class.c (instantiate_type): Change error message text.
+       * typeck2.c (store_init_value): Likewise.
+
 Mon Jan 23 21:57:14 1995  Mike Stump  <mrs@cygnus.com>
 
        * pt.c (tsubst): When we copy a node, don't forget to copy
@@ -4034,11 +4373,6 @@ Fri Apr 22 03:27:26 1994  Doug Evans  (dje@cygnus.com)
        * Language directory reorganization.
        See parent makefile.
 
-Fri Apr 22 03:27:26 1994  Doug Evans  (dje@cygnus.com)
-
-       * Language directory reorganization.
-       See parent makefile.
-
 Thu Apr 21 18:27:57 1994  Per Bothner  (bothner@kalessin.cygnus.com)
 
        * cp-tree.h (THUNK_DELTA):  It is normally negative, so
index f94d82424b02df0cc094f9956f299c4d6c635460..dd267f3784145f586982bb1f1b06ec2ad325b980 100644 (file)
@@ -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)
index be7cf3c64fada6820bc12727f904c6729804a2e8..3079d147734c34dad885c16a8b42c071e6955426 100644 (file)
@@ -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
 
index b0332e9af76716852734eac0ce64a456329964aa..f296dc9b421b6ae15513cad095fe3f02afa7c5cb 100644 (file)
@@ -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.  */
 
index 766e308e370776d0171ed1c3ef6fc11d0337e73b..528c23a03d6c105aae67d9d790cb1299d46ef2fb 100644 (file)
@@ -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));
index ce01c662ccfa6071ded5c8105b7c2ef6e94df788..e87b168a23325e6f9cb00ad9026e5b18c61c2f26 100644 (file)
@@ -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. */
index aad3dfb04b0a5566174c2bbf698df7dd22249dd1..1ef0ebd8f19a8948a78a0f997ac440ad9900831a 100644 (file)
@@ -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);
 }
index b0e5c00c56949c71e8288020688610b936ebdc8d..6cc04204cd9a23883cb1b7d7d623172fdb9851f1 100644 (file)
@@ -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
index 2be11e0d90daf62c7778b3ae8140d478944954f6..215dd17924033c278d4d3030827b490c38abaad0 100644 (file)
@@ -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));
index 6fc23ec85cdf30dd68d70b34fd46d5e1ecabde35..607d5034f2a55f3255912c7bd720c46b6f61345a 100644 (file)
@@ -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
index 63a909cb457835a87e59fd8d58fae9ed8aa3fb85..01c5bcb896a3140d4b49470140a71cd7307c042c 100644 (file)
@@ -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);
 
index 89a90ded3fac839d6641163b1384c681c8537171..6cbc00671b29538841670eb51553ffbda8a90e40 100644 (file)
@@ -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;
index f185ebe17695c40a816da8aeeb6fedfd8fbed7bf..29b64e69e3dd246f8a631e61fab793fcc595712e 100644 (file)
@@ -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 ();
 
index c51c756700a3f506ced4381f6b8b0035ecbf355f..d9430eca6cb1cff9f15f7c6522e9ccb518872199 100644 (file)
@@ -1074,8 +1074,10 @@ unary_expr:
                    {
                      tree t = TREE_VALUE ($2);
                      if (t != NULL_TREE
-                         && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
-                       pedwarn ("ANSI C++ forbids using sizeof() on a function");
+                         && ((TREE_TYPE (t)
+                             && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+                             || is_overloaded_fn (t)))
+                       pedwarn ("ANSI C++ forbids taking the sizeof a function type");
                    }
                  $$ = c_sizeof (TREE_TYPE ($2)); }
        | SIZEOF '(' type_id ')'  %prec HYPERUNARY
@@ -1142,7 +1144,7 @@ new_initializer:
           syntactically valid but semantically invalid.  */
        | '=' init
                {
-                 if (flag_ansi)
+                 if (pedantic)
                    pedwarn ("ANSI C++ forbids initialization of new expression with `='");
                  $$ = $2;
                }
@@ -1169,7 +1171,7 @@ cast_expr:
                { 
                  tree init = build_nt (CONSTRUCTOR, NULL_TREE,
                                        nreverse ($3)); 
-                 if (flag_ansi)
+                 if (pedantic)
                    pedwarn ("ANSI C++ forbids constructor-expressions");
                  /* Indicate that this was a GNU C constructor expression.  */
                  TREE_HAS_CONSTRUCTOR (init) = 1;
@@ -1289,7 +1291,6 @@ unqualified_id:
 
 expr_or_declarator:
          notype_unqualified_id
-       | notype_qualified_id
        | '*' expr_or_declarator %prec UNARY
                { $$ = build_parse_node (INDIRECT_REF, $2); }
        | '&' expr_or_declarator %prec UNARY
@@ -1301,9 +1302,6 @@ expr_or_declarator:
 direct_notype_declarator:
          complex_direct_notype_declarator
        | notype_unqualified_id
-       | notype_qualified_id
-               { push_nested_class (TREE_TYPE (OP0 ($$)), 3);
-                 TREE_COMPLEXITY ($$) = current_class_depth; }
        | '(' expr_or_declarator ')'
                { $$ = finish_decl_parsing ($2); }
        ;
@@ -1360,7 +1358,7 @@ primary:
                  $<ttype>$ = expand_start_stmt_expr (); }
          compstmt ')'
                { tree rtl_exp;
-                 if (flag_ansi)
+                 if (pedantic)
                    pedwarn ("ANSI C++ forbids braced-groups within expressions");
                  rtl_exp = expand_end_stmt_expr ($<ttype>2);
                  /* The statements have side effects, so the group does.  */
@@ -1554,7 +1552,7 @@ primary:
        | object unqualified_id  %prec UNARY
                { got_object = NULL_TREE;
                  $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
-       | object qualified_id %prec UNARY
+       | object overqualified_id %prec UNARY
                { got_object = NULL_TREE;
                  $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
        | object unqualified_id '(' nonnull_exprlist ')'
@@ -1589,7 +1587,7 @@ primary:
                                          (LOOKUP_NORMAL|LOOKUP_AGGR));
 #endif
                }
-       | object qualified_id '(' nonnull_exprlist ')'
+       | object overqualified_id '(' nonnull_exprlist ')'
                {
                  got_object = NULL_TREE;
                  if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
@@ -1601,7 +1599,7 @@ primary:
                  else
                    $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
                }
-       | object qualified_id LEFT_RIGHT
+       | object overqualified_id LEFT_RIGHT
                {
                  got_object = NULL_TREE;
                  if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
@@ -1617,8 +1615,9 @@ primary:
        | object '~' TYPESPEC LEFT_RIGHT
                {
                  got_object = NULL_TREE;
-                 if (TREE_CODE (TREE_TYPE ($1)) 
-                     != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3))))
+                 if (IDENTIFIER_GLOBAL_VALUE ($3)
+                     && (TREE_CODE (TREE_TYPE ($1)) 
+                         != TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE ($3)))))
                    cp_error ("`%E' is not of type `%T'", $1, $3);
                  $$ = convert (void_type_node, $1);
                }
@@ -1654,7 +1653,7 @@ primary_no_id:
                    }
                  $<ttype>$ = expand_start_stmt_expr (); }
          compstmt ')'
-               { if (flag_ansi)
+               { if (pedantic)
                    pedwarn ("ANSI C++ forbids braced-groups within expressions");
                  $$ = expand_end_stmt_expr ($<ttype>2); }
        | primary_no_id '(' nonnull_exprlist ')'
@@ -1816,6 +1815,8 @@ typed_declspecs1:
                { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
        | typespec reserved_declspecs   %prec HYPERUNARY
                { $$ = decl_tree_cons (NULL_TREE, $$, $2); }
+       | typespec reserved_typespecquals reserved_declspecs
+               { $$ = decl_tree_cons (NULL_TREE, $$, chainon ($2, $3)); }
        | declmods typespec reserved_declspecs
                { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
        | declmods typespec reserved_typespecquals
@@ -1902,11 +1903,11 @@ typespec: structsp
        | complete_type_name
        | TYPEOF '(' expr ')'
                { $$ = TREE_TYPE ($3);
-                 if (flag_ansi)
+                 if (pedantic)
                    pedwarn ("ANSI C++ forbids `typeof'"); }
        | TYPEOF '(' type_id ')'
                { $$ = groktypename ($3);
-                 if (flag_ansi)
+                 if (pedantic)
                    pedwarn ("ANSI C++ forbids `typeof'"); }
        | SIGOF '(' expr ')'
                { tree type = TREE_TYPE ($3);
@@ -2763,7 +2764,7 @@ new_type_id:
           non-constant dimension.  */
        | '(' type_id ')' '[' expr ']'
                {
-                 if (flag_ansi)
+                 if (pedantic)
                    pedwarn ("ANSI C++ forbids array dimensions with parenthesized type in new");
                  $$ = build_parse_node (ARRAY_REF, TREE_VALUE ($2), $5);
                  $$ = build_decl_list (TREE_PURPOSE ($2), $$);
@@ -2905,6 +2906,9 @@ complex_direct_notype_declarator:
                { $$ = build_parse_node (ARRAY_REF, $$, $3); }
        | direct_notype_declarator '[' ']'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
+       | notype_qualified_id
+               { push_nested_class (TREE_TYPE (OP0 ($$)), 3);
+                 TREE_COMPLEXITY ($$) = current_class_depth; }
        ;
 
 qualified_id:
@@ -3107,7 +3111,7 @@ errstmt:  error ';'
 maybe_label_decls:
          /* empty */
        | label_decls
-               { if (flag_ansi)
+               { if (pedantic)
                    pedwarn ("ANSI C++ forbids label declarations"); }
        ;
 
@@ -3323,7 +3327,7 @@ simple_stmt:
                  register tree label
                    = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
 
-                 if (flag_ansi)
+                 if (pedantic)
                    pedwarn ("ANSI C++ forbids range expressions in switch statement");
                  if (value1 != error_mark_node
                      && value2 != error_mark_node)
index 5804bb6b87c724daa6331f49ba8c49752a012dcf..5ac3b633b3f1a945d72e5e68e35c31c1cf24d885 100644 (file)
@@ -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);
index 4424423b07be775de44326048343b1bad36d2eb8..763d768148caa1c1c59f94810fcf4b0c362ff7e4 100644 (file)
@@ -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
index b21bbe94567fbced996377bdec94850397d22047..b7f51d2a3fd9e14b4ea019f6a6c9a40bd84591b2 100644 (file)
@@ -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,
index 8a446c18f37017afe32b79c1e17c4ba678ede4e6..38015215f91e9657675ee34b1b69cd97f759e79f 100644 (file)
@@ -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);