OSDN Git Service

53rd Cygnus<->FSF merge
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Jan 1995 08:19:58 +0000 (08:19 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 24 Jan 1995 08:19:58 +0000 (08:19 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@8794 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/cp/ChangeLog
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/except.c
gcc/cp/gxx.gperf
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/lex.h
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/spew.c
gcc/cp/tree.c
gcc/cp/typeck.c

index 7574f80..6667807 100644 (file)
+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
+       TREE_CHAIN, we use it later.
+
+Mon Jan 23 03:33:47 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (convert_for_assignment): Initialize variable before use.
+
+Fri Jan 20 01:17:59 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * g++.c (main): Link with both libstdc++ and libg++ if called as
+       something ending with "g++", otherwise only libstdc++.  Move -lm to
+       the end of the line.
+
+Thu Jan 19 15:43:11 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (build_method_call): Don't mess with 'this' before calling
+        compute_conversion_costs.
+
+Wed Jan 18 15:40:55 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * search.c (get_matching_virtual): Give line number for previous
+        declaration.
+
+       * call.c (convert_harshness): Handle conversions to references
+       better.
+
+       * cvt.c (build_up_reference): OK, handle {MIN,MAX}_EXPR *properly*.
+
+Wed Jan 18 15:21:38 1995  Mike Stump  <mrs@cygnus.com>
+
+       * class.c (instantiate_type): Use DECL_CHAIN to walk lists instead,
+       as the TREE_CHAIN for methods will take us to the next differently
+       named function, DECL_CHAIN won't.
+
+Wed Jan 18 14:26:59 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * tree.c (lvalue_p): Handle {MIN,MAX}_EXPR.
+
+       * decl2.c (lang_decode_option): -Wall implies -Wparentheses.
+       warn_parentheses defaults to 0.
+
+       * decl.c (grokparms): Put back call to require_instantiated_type.
+
+Tue Jan 17 19:56:15 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c (exception_section): Use the data section on the rs6000.
+       Change calling convention for named_section.
+
+Wed Jan 17 18:20:57 1994  Fergus Henderson <fjh@munta.cs.mu.oz.au>
+
+        * cp-tree.h : Make if (x=0) warn with wall
+        * parse.y : Make if (x=0) warn with wall
+
 Tue Jan 17 14:12:00 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
-        * cvt.c (cp_convert): Just call truthvalue_conversion to convert to
+       * decl.c (BOOL_TYPE_SIZE): BITS_PER_WORD if SLOW_BYTE_ACCESS,
+       BITS_PER_UNIT otherwise.
+
+       * search.c (get_matching_virtual): Don't check the binfo if the
+       types are the same.
+
+       * cvt.c (cp_convert): Just call truthvalue_conversion to convert to
         bool.
 
 Mon Jan 16 13:28:48 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
-        * various: Use boolean_type_node, boolean_true_node,
-        boolean_false_node.
+       * various: Use boolean_type_node, boolean_true_node,
+       boolean_false_node.
+
+       * search.c (get_matching_virtual): Allow covariant returns that
+       don't require pointer adjustment.
+
+       * typeck.c (build_conditional_expr): Don't call default_conversion
+       on ifexp.
+
+       * cvt.c (build_up_reference): Handle MIN_EXPR and MAX_EXPR.
+
+       * decl.c (grokdeclarator): Upgrade warning about &const to pedwarn.
+
+Sun Jan 15 22:17:32 1995  dcb@lovat.fmrco.COM (David Binderman)
+
+       * pt.c (do_function_instantiation): Free targs once we're done.
 
 Sun Jan 15 22:17:32 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
 
-        * decl.c (BOOL_TYPE_SIZE): Defaults to BITS_PER_WORD.
-        (init_decl_processing): Use BOOL_TYPE_SIZE instead of CHAR_TYPE_SIZE
-        for bool.
+       * decl.c (BOOL_TYPE_SIZE): Defaults to BITS_PER_WORD.
+       (init_decl_processing): Use BOOL_TYPE_SIZE instead of CHAR_TYPE_SIZE
+       for bool.
+
+Sat Jan 14 05:33:55 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl2.c (finish_file): We need to mess up if there are any
+       variables in the list, not just if there is one with a constructor.
+
+Fri Jan 13 14:42:55 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (duplicate_decls): Propagate DECL_STATIC_{CON,DE}STRUCTOR.
+       (finish_function): Handle DECL_STATIC_{CON,DE}STRUCTOR.
+       (finish_function): Trust rest_of_compilation.
+
+       * decl2.c (finish_file): Also call functions designated as static
+       constructors/destructors.
+
+       * decl.c (grokdeclarator): Allow access decls of operator functions.
+       (grokparms): Only do convert_for_initialization if the initializer
+       has a type.
+       (duplicate_decls): Put back push_obstacks_nochange call.
+
+       * lex.c (real_yylex): Downgrade complaint about the escape sequence
+       being too large from pedwarn to warning.
+
+       * decl.c (grokdeclarator): Don't complain about long long in system
+       headers.
+
+       * lex.c (real_yylex): Handle digraphs.
+
+Thu Jan 12 12:17:24 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (init_decl_processing): -f{no-,}strict-prototype only
+       affects C linkage declarations now.
+
+       * typeck.c (comp_target_types): Grok simple contravariant conversions.
+       (common_type): t1 and t2 are interchangeable.
+
+       * various: Test return value of comp_target_types differently in
+       different places; it now returns -1 for a contravariant conversion
+       (which is fine in symmetric cases).
+
+       (common_type): Prefer long double to double even when
+       they have the same precision.
+
+       * decl.c (grokparms): Call convert_for_initialization to check
+       default arguments.
+
+       * init.c (build_new): void_type_node has a size (of 0).
+
+       * decl.c (decls_match): Also check for agreement of TREE_READONLY
+       and TREE_THIS_VOLATILE.
+       (push_class_level_binding): Properly handle shadowing of
+       nested tags by fields.
+
+       * search.c (dfs_pushdecls): Ditto.
+
+       * decl2.c (finish_file): Don't second-guess self-initialization.
+
+       * cvt.c (convert_to_reference): Work with expr directly, rather than
+       a copy.
+
+       * decl.c (push_overloaded_decl): Only shadow artificial TYPE_DECLs.
+
+       * init.c (add_friend): Downgrade duplicate friend message from
+       pedwarn to warning.
+
+       * decl.c (duplicate_decls): Push obstacks before calling common_type.
+
+Thu Jan 12 17:15:21 1995  Michael Ben-Gershon  <mybg@cs.huji.ac.il>
+
+       * except.c (push_eh_entry): set LABEL_PRESERVE_P flag for
+       exception table labels.
+       (expand_start_all_catch): Ditto.
+       (expand_leftover_cleanups): Ditto.
+       (expand_end_catch_block): Ditto.
+       * except.c (make_first_label): new function.
+       (expand_start_all_catch): add a call to make_first_label() before
+       using a label as a jump destination.
+       (expand_end_all_catch): Ditto.
+       (expand_leftover_cleanups): Ditto.
+       (expand_end_catch_block): Ditto.
+       (expand_builtin_throw): Ditto.
+       (expand_throw): Ditto.
+       * except.c: Add ARM processor support for exception handling.
+
+Thu Jan 12 12:17:24 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       (complete_array_type): Copy code from C frontend.
+
+       * lex.c (real_yylex): Don't multiply the length of a wide string
+       literal by WCHAR_BYTES.
+
+       * decl.c (pushdecl): Check for redeclaration of wchar_t here.
+       (duplicate_decls): Instead of here.
+       (define_label): Complain about a label named wchar_t.
+       (grokdeclarator): Complain about declarations of
+       operator-function-ids as non-functions.
+
+       * typeck.c (unary_complex_lvalue): Also wrap prefix -- and ++ in
+       COMPOUND_EXPRs.
+       (build_unary_op): Wrap unary plus in a NON_LVALUE_EXPR.
+
+       * lex.c (real_yylex): Don't skip whitespace when reading the next
+       character after ->.
+
+Wed Jan 11 16:32:49 1995  Mike Stump  <mrs@cygnus.com>
+
+       * except.c: Allow cc1plus to be built with native compiler on rs6000.
+       (expand_start_all_catch): Add assemble_external calls for various
+       routines we call.
+       (expand_leftover_cleanups): Ditto.
+       (expand_start_catch_block): Ditto.
+       (do_unwind): Ditto.
+       (expand_builtin_throw): Ditto.
+
+Wed Jan 11 01:05:42 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (pushtag): Only look for a previous decl in the current
+       binding level.  Use explicit global scope in DECL_NESTED_TYPENAME.
+
+       * gxx.gperf: Add __signature__ and __sigof__ keywords.
+
+       * decl2.c (lang_decode_option): -ansi does not set flag_no_asm.  It
+       does set flag_no_gnu_keywords and flag_operator_names.
+
+       * lex.c (init_lex): 'overload' is not a keyword unless -traditional.
+       Unset extension keywords if -fno-gnu-keywords.
+       Allow operator names ('bitand') if -foperator-names.
+       Never unset 'asm'; -fno-asm only affects 'typeof'.
+
+       * decl.c (lookup_name_real): The got_object special lookup only
+       applies to types.
+
+Tue Jan 10 18:07:51 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * spew.c (yylex): Also use DECL_NESTED_TYPENAME if got_object is set.
+
+       * parse.y (primary): Unset got_object after all rules that use the
+        'object' nonterminal.
+       (object): Set got_object.
+
+       * lex.h: Declare got_object.
+
+       * decl.c (lookup_name_real): Also lookup names in the context of an
+       object specified.
+
+Tue Jan 10 14:30:30 1995  Mike Stump  <mrs@cygnus.com>
+
+       * typeck.c (get_member_function_from_ptrfunc): Use ptrdiff_type_node
+       for things that have to be added to pointers, not size_type.  Cures
+       problems with pointer to members on Alphas.
+       (build_binary_op_nodefault): Ditto.
+       (get_delta_difference_: Ditto.
+       (build_ptrmemfunc): Ditto.
+
+Tue Jan 10 01:49:25 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (pushtag): Stick the new decl in TYPE_NAME before pushing
+       it.
+
+       * typeck.c (build_component_ref): Don't build up a COMPONENT_REF
+       when dealing with overloaded member functions; just act like
+       build_offset_ref.
+       (commonparms): Remove misleading comment.
+
+       * decl.c (duplicate_decls): Complain about repeated default
+       arguments here.
+       (redeclaration_error_message): Instead of here.
+       (pushdecl): Complain about missing default arguments here.
+       (grokparms): Instead of here.
+       (lookup_name_current_level): Also match on DECL_ASSEMBLER_NAME.
+       (grok_reference_init): Do not complain about missing initializer if
+       declared 'extern'.
+
+       * search.c (lookup_field): Don't return a TYPE_DECL if there is a
+       function alternative and want_type is not set.
+
+Mon Jan  9 18:16:23 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * decl.c (pushtag): Don't set TYPE_NAME to an identifier.  Do push
+       the decl when the type has no TYPE_NAME.
+       (lookup_nested_type): Don't assume that type has TYPE_NAME set.
+       (lookup_name_real): Call lookup_field with want_type =
+       prefer_type.
+
+       * search.c (lookup_field): Handle want_type properly in the presence
+       of fields with the same name.
+
+       * decl.c (set_nested_typename): Set nested name for file-scope types
+       to include leading ::.
+       (pushdecl): Set the nested typename if the decl doesn't have one,
+       rather than if the type's canonical decl doesn't have one.
+
+Mon Jan  9 16:48:16 1995  Steve Chamberlain  (sac@jonny.cygnus.com)
+
+       * typeck.c (pointer_int_sum):  Use offset size when calculating
+       index expression.
+
+Mon Jan  9 03:44:33 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * typeck.c (convert_for_assignment): Complain about contravariance
+       violation here.
+       (comp_target_types): Instead of here.
+       (build_unary_op): resolve_offset_ref before checking for a valid
+       type.
+
+       * spew.c (yylex): Decrement looking_for_typename after we see a
+       _DEFN.
+
+       * decl.c (pushdecl): Don't install an artificial TYPE_DECL in
+        IDENTIFIER_LOCAL_VALUE if we already have a decl with that name.
+
+       * typeck.c (convert_for_assignment): Converting pointers to bool
+       does not need a cast.
+
+Sun Jan  8 18:16:45 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * class.c (instantiate_type): Initialize nsubsts parm.
+
+       * pt.c (do_function_instantiation): Ditto.
+
+Sat Jan  7 14:37:05 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * pt.c (tsubst): Use TREE_STATIC instead of DECL_INLINE &&
+       DECL_SAVED_INSNS to determine whether or not we've seen a definition
+       of this function.
+       (instantiate_template): Ditto.
+
+       * call.c (convert_harshness): Allow const reference binding when
+       called from the overloading code, but not when called from
+       can_convert (since it isn't a conversion).
+       (convert_harshness): Put back some disabled code.
+
+Fri Jan  6 14:10:57 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (convert_harshness): There is no implicit conversion from
+       void* to other pointer types (unless the parameter is (void*)0).
+       (convert_harshness): Non-lvalues do not convert to reference types.
+
+       * class.c (finish_struct_methods): Still set
+        TYPE_HAS_{INT,REAL}_CONVERSION.
+
+       * call.c (can_convert): Don't use aggregate initialization.
+
+       * cp-tree.h: Declare lookup_conversions.
+
+Thu Jan  5 21:08:00 1995  Mike Stump  <mrs@cygnus.com>
+
+       * parse.y (simple_stmt): Fix duplicate case value error messages to
+       be more readable.
+
+Wed Jan  4 16:44:19 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * cvt.c (build_type_conversion): Total rewrite to use
+       convert_harshness instead of reproducing conversion logic here.  Now
+       much shorter.
+
+       * call.c (convert_harshness): Support conversions to bool.
+       (can_convert): Checks whether a conversion is less harsh
+       than USER_CODE, for build_type_conversion.
+
+       * search.c (add_conversions): Function for passing to dfs_walk which
+       adds all the type conversion operators in the current type to a list.
+       (lookup_conversions): Calls dfs_walk with add_conversions and return
+       the list.
+       (dfs_walk): Don't require a qfn.
+
+       * cp-tree.h: Lose CLASSTYPE_CONVERSIONS hackery.
+       (CLASSTYPE_FIRST_CONVERSION): Points to elt 1 of CLASSTYPE_METHOD_VEC.
+
+       * class.c (finish_struct_bits): Lose CLASSTYPE_CONVERSIONS hackery.
+       (grow_method): A separate function for building onto the growing
+       method vector.
+       (finish_struct_methods): Use it.  Put all type conversion operators
+       right after the constructors.  Perhaps we should sort the methods
+        alphabetically?
+
+Mon Jan  2 14:42:58 1995  Jason Merrill  <jason@phydeaux.cygnus.com>
+
+       * call.c (build_method_call): Lose another misleading shortcut.
+
+Fri Dec 30 17:57:30 1994  Mike Stump  <mrs@cygnus.com>
+
+       * gc.c (build_bltn_desc): Handle bool as a built-in type.
+
+Fri Dec 30 14:20:21 1994  Mike Stump  <mrs@cygnus.com>
+
+       * tree.c (layout_vbasetypes): Ensure that we don't loose alignment
+       on the complete type because of small virtual bases.
 
 Fri Dec 30 12:22:29 1994  Mike Stump  <mrs@cygnus.com>
 
index 85a2788..7a71f40 100644 (file)
@@ -47,6 +47,7 @@ extern tree unary_complex_lvalue ();
 static struct harshness_code convert_harshness ();
 
 #define EVIL_RETURN(ARG)       ((ARG).code = EVIL_CODE, (ARG))
+#define STD_RETURN(ARG)                ((ARG).code = STD_CODE, (ARG))
 #define QUAL_RETURN(ARG)       ((ARG).code = QUAL_CODE, (ARG))
 #define TRIVIAL_RETURN(ARG)    ((ARG).code = TRIVIAL_CODE, (ARG))
 #define ZERO_RETURN(ARG)       ((ARG).code = 0, (ARG))
@@ -117,6 +118,7 @@ convert_harshness (type, parmtype, parm)
   struct harshness_code h;
   register enum tree_code codel;
   register enum tree_code coder;
+  int lvalue;
 
   h.code = 0;
   h.distance = 0;
@@ -136,7 +138,12 @@ convert_harshness (type, parmtype, parm)
       if (parm)
        parm = convert_from_reference (parm);
       parmtype = TREE_TYPE (parmtype);
+      lvalue = 1;
     }
+  else if (parm)
+    lvalue = lvalue_p (parm);
+  else
+    lvalue = 0;
 
   codel = TREE_CODE (type);
   coder = TREE_CODE (parmtype);
@@ -300,6 +307,14 @@ convert_harshness (type, parmtype, parm)
   if (coder == VOID_TYPE)
     return EVIL_RETURN (h);
 
+  if (codel == BOOLEAN_TYPE)
+    {
+      if (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE
+         || coder == POINTER_TYPE || coder == OFFSET_TYPE)
+       return STD_RETURN (h);
+      return EVIL_RETURN (h);
+    }
+
   if (INTEGRAL_CODE_P (codel))
     {
       /* Control equivalence of ints an enums.  */
@@ -375,11 +390,10 @@ convert_harshness (type, parmtype, parm)
       register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype));
       int penalty = 4 * (ttl != ttr);
 
-      /* Anything converts to void *.  void * converts to anything.
-        Since these may be `const void *' (etc.) use VOID_TYPE
-        instead of void_type_node.  Otherwise, the targets must be the same,
-        except that we do allow (at some cost) conversion between signed and
-        unsigned pointer types.  */
+      /* Anything converts to void *.  Since this may be `const void *'
+        (etc.) use VOID_TYPE instead of void_type_node.  Otherwise, the
+        targets must be the same, except that we do allow (at some cost)
+        conversion between signed and unsigned pointer types.  */
 
       if ((TREE_CODE (ttl) == METHOD_TYPE
           || TREE_CODE (ttl) == FUNCTION_TYPE)
@@ -396,7 +410,8 @@ convert_harshness (type, parmtype, parm)
        }
 
 #if 1
-      if (TREE_CODE (ttl) != VOID_TYPE && TREE_CODE (ttr) != VOID_TYPE)
+      if (TREE_CODE (ttl) != VOID_TYPE
+         && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
        {
          if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr))
            {
@@ -404,7 +419,7 @@ convert_harshness (type, parmtype, parm)
              ttr = unsigned_type (ttr);
              penalty = 10;
            }
-         if (! comp_target_types (ttl, ttr, 0))
+         if (comp_target_types (ttl, ttr, 0) <= 0)
            return EVIL_RETURN (h);
        }
 #else
@@ -414,7 +429,7 @@ convert_harshness (type, parmtype, parm)
                && (ttl = unsigned_type (ttl),
                    ttr = unsigned_type (ttr),
                    penalty = 10, 0))
-           || (comp_target_types (ttl, ttr, 0))))
+           || (comp_target_types (ttl, ttr, 0) > 0)))
        return EVIL_RETURN (h);
 #endif
 
@@ -503,14 +518,21 @@ convert_harshness (type, parmtype, parm)
 
       ttl = TREE_TYPE (type);
 
-      /* When passing a non-const argument into a const reference (or vice
-        versa), dig it a little, so a non-const reference is preferred
-        over this one. (mrs) */
-      if (TYPE_READONLY (ttl) != constp
-         || TYPE_VOLATILE (ttl) != volatilep)
-       penalty = 2;
-      else
-       penalty = 0;
+      /* Only allow const reference binding if we were given a parm to deal
+         with, since it isn't really a conversion.  This is a hack to
+         prevent build_type_conversion from finding this conversion, but
+         still allow overloading to find it.  */
+      if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
+       return EVIL_RETURN (h);
+
+      if (TYPE_READONLY (ttl) < constp
+         || TYPE_VOLATILE (ttl) < volatilep)
+       return EVIL_RETURN (h);
+
+      /* When passing a non-const argument into a const reference, dig it a
+        little, so a non-const reference is preferred over this one.  */
+      penalty = ((TYPE_READONLY (ttl) > constp)
+                + (TYPE_VOLATILE (ttl) > volatilep));
 
       ttl = TYPE_MAIN_VARIANT (ttl);
 
@@ -520,98 +542,17 @@ convert_harshness (type, parmtype, parm)
          form = TREE_CODE (intype);
        }
 
-      if (ttl == intype && penalty == 0)
-       return ZERO_RETURN (h);
-      else
-       penalty = 2;
-
       ttr = intype;
 
-      /* If the initializer is not an lvalue, then it does not
-        matter if we make life easier for the programmer
-        by creating a temporary variable with which to
-        hold the result.  */
-      if (parm && (INTEGRAL_CODE_P (coder)
-                  || coder == REAL_TYPE)
-         && ! lvalue_p (parm))
-       {
-         h = convert_harshness (ttl, ttr, NULL_TREE);
-         if (penalty > 2 || h.code != 0)
-           h.code |= STD_CODE;
-         else
-           h.code |= TRIVIAL_CODE;
-         h.distance = 0;
-         return h;
-       }
-
-      if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
-       {
-         ttl = unsigned_type (ttl);
-         ttr = intype = unsigned_type (intype);
-         penalty += 2;
-       }
-
-      if (ttl == ttr)
-       {
-         if (penalty > 2)
-           {
-             h.code = STD_CODE;
-             h.distance = 0;
-           }
-         else
-           {
-             h.code = TRIVIAL_CODE;
-             /* We set this here so that build_overload_call_real will be
-                able to see the penalty we found, rather than just looking
-                at a TRIVIAL_CODE with no other information.  */
-             h.int_penalty = penalty;
-           }
-         return h;
-       }
+      /* Maybe handle conversion to base here?  */
 
-      /* Pointers to voids always convert for pointers.  But
-        make them less natural than more specific matches.  */
-      if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
+      h = convert_harshness (ttl, ttr, NULL_TREE);
+      if (penalty && h.code == 0)
        {
-         if (TREE_TYPE (ttl) == void_type_node
-             || TREE_TYPE (ttr) == void_type_node)
-           {
-             h.code = STD_CODE;
-             h.distance = 0;
-             return h;
-           }
-       }
-
-      /* Here it does matter.  If this conversion is from derived to base,
-        allow it.  Otherwise, types must be compatible in the strong sense.  */
-      if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
-       {
-         int b_or_d = get_base_distance (ttl, ttr, 0, 0);
-         if (b_or_d < 0)
-           {
-             b_or_d = get_base_distance (ttr, ttl, 0, 0);
-             if (b_or_d < 0)
-               return EVIL_RETURN (h);
-             h.distance = -b_or_d;
-           }
-         /* Say that this conversion is relatively painless.
-            If it turns out that there is a user-defined X(X&)
-            constructor, then that will be invoked, but that's
-            preferable to dealing with other user-defined conversions
-            that may produce surprising results.  */
-         else
-           h.distance = b_or_d;
-         h.code = STD_CODE;
-         return h;
-       }
-
-      if (comp_target_types (ttl, intype, 1))
-       {
-         if (penalty)
-           h.code = STD_CODE;
-         h.distance = 0;
-         return h;
+         h.code = QUAL_CODE;
+         h.int_penalty = penalty;
        }
+      return h;
     }
   if (codel == RECORD_TYPE && coder == RECORD_TYPE)
     {
@@ -631,6 +572,15 @@ convert_harshness (type, parmtype, parm)
   return EVIL_RETURN (h);
 }
 
+int
+can_convert (to, from)
+     tree to, from;
+{
+  struct harshness_code h;
+  h = convert_harshness (to, from, NULL_TREE);
+  return h.code < USER_CODE;
+}
+
 #ifdef DEBUG_MATCHING
 static char *
 print_harshness (h)
@@ -2134,6 +2084,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
            basetype_path = TREE_VALUE (basetype_path);
          basetype = BINFO_TYPE (basetype_path);
 
+#if 0
          /* Cast the instance variable if necessary.  */
          if (basetype != TYPE_MAIN_VARIANT
              (TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)))))
@@ -2152,6 +2103,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
             the access-control rewrite will make this change more cleanly.  */
          if (TREE_VALUE (parms) == error_mark_node)
            return error_mark_node;
+#endif
 
          if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
            function = DECL_CHAIN (function);
@@ -2208,19 +2160,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
                          && (cp->h.code & USER_CODE))
                        continue;
 
-                     /* If we used default parameters, we must
-                        check to see whether anyone else might
-                        use them also, and report a possible
-                        ambiguity.  */
-                     if (! TYPE_USES_MULTIPLE_INHERITANCE (save_basetype)
-                         && cp->harshness[len].distance == 0
-                         && cp->h.code < best)
-                       {
-                         if (! DECL_STATIC_FUNCTION_P (function))
-                           TREE_VALUE (parms) = cp->arg;
-                         if (best == 1)
-                           goto found_and_maybe_warn;
-                       }
                      cp++;
                    }
                }
index b0e0cf8..8076406 100644 (file)
@@ -1687,63 +1687,6 @@ finish_struct_bits (t, max_has_virtual)
        }
     }
 
-  /* Need to test METHOD_VEC here in case all methods
-     (conversions and otherwise) are inherited.  */
-  if (TYPE_HAS_CONVERSION (t) && method_vec != NULL_TREE)
-    {
-      tree first_conversions[last_conversion_type];
-      tree last_conversions[last_conversion_type];
-      enum conversion_type conv_index;
-      tree *tmp;
-      int i;
-
-      bzero ((char *) first_conversions, sizeof (first_conversions));
-      bzero ((char *) last_conversions, sizeof (last_conversions));
-      for (tmp = &TREE_VEC_ELT (method_vec, 1);
-          tmp != TREE_VEC_END (method_vec); tmp += 1)
-       {
-         /* ??? This should compare DECL_NAME (*tmp) == ansi_opname[TYPE_EXPR].  */
-         if (IDENTIFIER_TYPENAME_P (DECL_ASSEMBLER_NAME (*tmp)))
-           {
-             tree fntype = TREE_TYPE (*tmp);
-             tree return_type = TREE_TYPE (fntype);
-             my_friendly_assert (TREE_CODE (fntype) == METHOD_TYPE, 171);
-
-             if (typecode_p (return_type, POINTER_TYPE))
-               {
-                 if (TYPE_READONLY (TREE_TYPE (return_type)))
-                   conv_index = constptr_conv;
-                 else
-                   conv_index = ptr_conv;
-               }
-             else if (typecode_p (return_type, INTEGER_TYPE)
-                      || typecode_p (return_type, BOOLEAN_TYPE)
-                      || typecode_p (return_type, ENUMERAL_TYPE))
-               {
-                 TYPE_HAS_INT_CONVERSION (t) = 1;
-                 conv_index = int_conv;
-               }
-             else if (typecode_p (return_type, REAL_TYPE))
-               {
-                 TYPE_HAS_REAL_CONVERSION (t) = 1;
-                 conv_index = real_conv;
-               }
-             else
-               continue;
-
-             if (first_conversions[(int) conv_index] == NULL_TREE)
-               first_conversions[(int) conv_index] = *tmp;
-             last_conversions[(int) conv_index] = *tmp;
-           }
-       }
-
-      for (i = 0; i < (int) last_conversion_type; i++)
-       if (first_conversions[i] != last_conversions[i])
-         CLASSTYPE_CONVERSION (t, i) = error_mark_node;
-       else
-         CLASSTYPE_CONVERSION (t, i) = first_conversions[i];
-    }
-
   /* If this type has constructors, force its mode to be BLKmode,
      and force its TREE_ADDRESSABLE bit to be nonzero.  */
   if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t))
@@ -1761,6 +1704,57 @@ finish_struct_bits (t, max_has_virtual)
     }
 }
 
+/* Add FN to the method_vec growing on the class_obstack.  Used by
+   finish_struct_methods.  */
+static void
+grow_method (fn)
+     tree fn;
+{
+  tree method_vec = (tree)obstack_base (&class_obstack);
+  tree *testp = &TREE_VEC_ELT (method_vec, 0);
+  if (*testp == NULL_TREE)
+    testp++;
+  while (((HOST_WIDE_INT) testp
+         < (HOST_WIDE_INT) obstack_next_free (&class_obstack))
+        && DECL_NAME (*testp) != DECL_NAME (fn))
+    testp++;
+  if ((HOST_WIDE_INT) testp
+      < (HOST_WIDE_INT) obstack_next_free (&class_obstack))
+    {
+      tree x, prev_x;
+
+      for (x = *testp; x; x = DECL_CHAIN (x))
+       {
+         if (DECL_NAME (fn) == ansi_opname[(int) DELETE_EXPR]
+             || DECL_NAME (fn) == ansi_opname[(int) VEC_DELETE_EXPR])
+           {
+             /* ANSI C++ June 5 1992 WP 12.5.5.1 */
+             cp_error_at ("`%D' overloaded", fn);
+             cp_error_at ("previous declaration as `%D' here", x);
+           }
+         if (DECL_ASSEMBLER_NAME (fn)==DECL_ASSEMBLER_NAME (x))
+           {
+             /* We complain about multiple destructors on sight,
+                so we do not repeat the warning here.  Friend-friend
+                ambiguities are warned about outside this loop.  */
+             if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn)))
+               cp_error_at ("ambiguous method `%#D' in structure", fn);
+             break;
+           }
+         prev_x = x;
+       }
+      if (x == 0)
+       {
+         if (*testp)
+           DECL_CHAIN (prev_x) = fn;
+         else
+           *testp = fn;
+       }
+    }
+  else
+    obstack_ptr_grow (&class_obstack, fn);
+}
+
 /* Warn about duplicate methods in fn_fields.  Also compact method
    lists so that lookup can be made faster.
 
@@ -1769,10 +1763,12 @@ finish_struct_bits (t, max_has_virtual)
 
    Data Structure: List of method lists.  The outer list is a
    TREE_LIST, whose TREE_PURPOSE field is the field name and the
-   TREE_VALUE is the TREE_CHAIN of the FUNCTION_DECLs.  Friends are
-   chained in the same way as member functions, but they live in the
-   TREE_TYPE field of the outer list.  That allows them to be quickly
-   deleted, and requires no extra storage.
+   TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs.  TREE_CHAIN
+   links the entire list of methods for TYPE_METHODS.  Friends are
+   chained in the same way as member functions (? TREE_CHAIN or
+   DECL_CHAIN), but they live in the TREE_TYPE field of the outer
+   list.  That allows them to be quickly deleted, and requires no
+   extra storage.
 
    If there are any constructors/destructors, they are moved to the
    front of the list.  This makes pushclass more efficient.
@@ -1789,6 +1785,8 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
      int nonprivate_method;
 {
   tree method_vec;
+  tree save_fn_fields = tree_cons (NULL_TREE, NULL_TREE, fn_fields);
+  tree lastp;
   tree name = constructor_name (t);
   int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
 
@@ -1802,17 +1800,15 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
   obstack_free (&class_obstack, method_vec);
   obstack_blank (&class_obstack, sizeof (struct tree_vec));
 
-  while (fn_fields)
+  /* First fill in entry 0 with the constructors, and the next few with
+     type conversion operators (if any).  */
+
+  for (lastp = save_fn_fields; fn_fields; fn_fields = TREE_CHAIN (lastp))
     {
-      /* NEXT Pointer, TEST Pointer, and BASE Pointer.  */
-      tree nextp, *testp;
       tree fn_name = DECL_NAME (fn_fields);
       if (fn_name == NULL_TREE)
        fn_name = name;
 
-      nextp = TREE_CHAIN (fn_fields);
-      TREE_CHAIN (fn_fields) = NULL_TREE;
-
       /* Clear out this flag.
 
         @@ Doug may figure out how to break
@@ -1840,8 +1836,45 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
                    TYPE_HAS_NONPUBLIC_CTOR (t) = 2;
                }
            }
+         /* Constructors are handled easily in search routines.  */
+         DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0);
+         TREE_VEC_ELT (method_vec, 0) = fn_fields;
        }
-      else if (fn_name == ansi_opname[(int) MODIFY_EXPR])
+      else if (IDENTIFIER_TYPENAME_P (fn_name))
+       {
+         tree return_type = TREE_TYPE (TREE_TYPE (fn_fields));
+
+         if (typecode_p (return_type, INTEGER_TYPE)
+             || typecode_p (return_type, BOOLEAN_TYPE)
+             || typecode_p (return_type, ENUMERAL_TYPE))
+           TYPE_HAS_INT_CONVERSION (t) = 1;
+         else if (typecode_p (return_type, REAL_TYPE))
+           TYPE_HAS_REAL_CONVERSION (t) = 1;
+
+         grow_method (fn_fields);
+       }
+      else
+       {
+         lastp = fn_fields;
+         continue;
+       }
+
+      TREE_CHAIN (lastp) = TREE_CHAIN (fn_fields);
+      TREE_CHAIN (fn_fields) = NULL_TREE;
+    }
+
+  fn_fields = TREE_CHAIN (save_fn_fields);
+  while (fn_fields)
+    {
+      tree nextp;
+      tree fn_name = DECL_NAME (fn_fields);
+      if (fn_name == NULL_TREE)
+       fn_name = name;
+
+      nextp = TREE_CHAIN (fn_fields);
+      TREE_CHAIN (fn_fields) = NULL_TREE;
+
+      if (fn_name == ansi_opname[(int) MODIFY_EXPR])
        {
          tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
 
@@ -1854,65 +1887,12 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
            }
        }
 
-      /* Constructors are handled easily in search routines.  */
-      if (fn_name == name)
-       {
-         DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0);
-         TREE_VEC_ELT (method_vec, 0) = fn_fields;
-       }
-      else
-       {
-         testp = &TREE_VEC_ELT (method_vec, 0);
-         if (*testp == NULL_TREE)
-           testp++;
-         while (((HOST_WIDE_INT) testp
-                 < (HOST_WIDE_INT) obstack_next_free (&class_obstack))
-                && DECL_NAME (*testp) != fn_name)
-           testp++;
-         if ((HOST_WIDE_INT) testp
-             < (HOST_WIDE_INT) obstack_next_free (&class_obstack))
-           {
-             tree x, prev_x;
-
-             for (x = *testp; x; x = DECL_CHAIN (x))
-               {
-                 if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR]
-                     || DECL_NAME (fn_fields)
-                        == ansi_opname[(int) VEC_DELETE_EXPR])
-                   {
-                     /* ANSI C++ June 5 1992 WP 12.5.5.1 */
-                     cp_error_at ("`%D' overloaded", fn_fields);
-                     cp_error_at ("previous declaration as `%D' here", x);
-                   }
-                 if (DECL_ASSEMBLER_NAME (fn_fields)==DECL_ASSEMBLER_NAME (x))
-                   {
-                     /* We complain about multiple destructors on sight,
-                        so we do not repeat the warning here.  Friend-friend
-                        ambiguities are warned about outside this loop.  */
-                     if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields)))
-                       cp_error_at ("ambiguous method `%#D' in structure",
-                                    fn_fields);
-                     break;
-                   }
-                 prev_x = x;
-               }
-             if (x == 0)
-               {
-                 if (*testp)
-                   DECL_CHAIN (prev_x) = fn_fields;
-                 else
-                   *testp = fn_fields;
-               }
-           }
-         else
-           {
-             obstack_ptr_grow (&class_obstack, fn_fields);
-             method_vec = (tree)obstack_base (&class_obstack);
-           }
-       }
+      grow_method (fn_fields);
       fn_fields = nextp;
     }
 
+  /* Update in case method_vec has moved.  */
+  method_vec = (tree)obstack_base (&class_obstack);
   TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack)
     - (&TREE_VEC_ELT (method_vec, 0));
   obstack_finish (&class_obstack);
@@ -4737,7 +4717,7 @@ instantiate_type (lhstype, rhs, complain)
        /* First look for an exact match  */
 
        while (field && TREE_TYPE (field) != lhstype)
-         field = TREE_CHAIN (field);
+         field = DECL_CHAIN (field);
        if (field)
          {
            TREE_OPERAND (rhs, 1) = field;
@@ -4747,13 +4727,13 @@ instantiate_type (lhstype, rhs, complain)
        /* No exact match found, look for a compatible function.  */
        field = TREE_OPERAND (rhs, 1);
        while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
-         field = TREE_CHAIN (field);
+         field = DECL_CHAIN (field);
        if (field)
          {
            TREE_OPERAND (rhs, 1) = field;
-           field = TREE_CHAIN (field);
+           field = DECL_CHAIN (field);
            while (field && ! comptypes (lhstype, TREE_TYPE (field), 0))
-             field = TREE_CHAIN (field);
+             field = DECL_CHAIN (field);
            if (field)
              {
                if (complain)
@@ -4821,7 +4801,7 @@ instantiate_type (lhstype, rhs, complain)
                  {
                    int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem));
                    tree *t = (tree *) alloca (sizeof (tree) * n);
-                   int i, d;
+                   int i, d = 0;
                    i = type_unification (DECL_TEMPLATE_PARMS (elem), t,
                                          TYPE_ARG_TYPES (TREE_TYPE (elem)),
                                          TYPE_ARG_TYPES (lhstype), &d, 0);
@@ -4845,14 +4825,15 @@ instantiate_type (lhstype, rhs, complain)
 
            /* No match found, look for a compatible function.  */
            elem = get_first_fn (rhs);
-           while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1))
+           while (elem && comp_target_types (lhstype,
+                                             TREE_TYPE (elem), 1) <= 0)
              elem = DECL_CHAIN (elem);
            if (elem)
              {
                tree save_elem = elem;
                elem = DECL_CHAIN (elem);
-               while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem),
-                                                   0))
+               while (elem && comp_target_types (lhstype,
+                                                 TREE_TYPE (elem), 0) <= 0)
                  elem = DECL_CHAIN (elem);
                if (elem)
                  {
@@ -4900,7 +4881,7 @@ instantiate_type (lhstype, rhs, complain)
              if (comptypes (lhstype, TREE_TYPE (elem), 1))
                return elem;
              else
-               elem = TREE_CHAIN (elem);
+               elem = DECL_CHAIN (elem);
          }
 
        /* No exact match found, look for a compatible method.  */
@@ -4908,14 +4889,16 @@ instantiate_type (lhstype, rhs, complain)
             baselink = next_baselink (baselink))
          {
            elem = TREE_VALUE (baselink);
-           while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1))
-             elem = TREE_CHAIN (elem);
+           while (elem && comp_target_types (lhstype,
+                                             TREE_TYPE (elem), 1) <= 0)
+             elem = DECL_CHAIN (elem);
            if (elem)
              {
                tree save_elem = elem;
-               elem = TREE_CHAIN (elem);
-               while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 0))
-                 elem = TREE_CHAIN (elem);
+               elem = DECL_CHAIN (elem);
+               while (elem && comp_target_types (lhstype,
+                                                 TREE_TYPE (elem), 0) <= 0)
+                 elem = DECL_CHAIN (elem);
                if (elem)
                  {
                    if (complain)
@@ -4940,7 +4923,7 @@ instantiate_type (lhstype, rhs, complain)
 #endif
          }
        if (complain)
-         error ("no static member functions named `%s'",
+         error ("no compatible member functions named `%s'",
                 IDENTIFIER_POINTER (name));
        return error_mark_node;
       }
index f3d3764..4f92ca3 100644 (file)
@@ -114,6 +114,14 @@ extern int pedantic;
 
 /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only.  */
 #define C_TYPE_FIELDS_READONLY(type) TYPE_LANG_FLAG_0 (type)
+
+/* Record in each node resulting from a binary operator
+   what operator was specified for it.  */
+#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
+
+/* Store a value in that field.  */
+#define C_SET_EXP_ORIGINAL_CODE(exp, code) \
+  (TREE_COMPLEXITY (exp) = (int)(code))
 \f
 /* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
    next exception handler.  */
@@ -271,7 +279,8 @@ extern int interface_only, interface_unknown;
 
 extern int flag_elide_constructors;
 
-/* Nonzero means handle things in ANSI, instead of GNU fashion.  */
+/* Nonzero means enable obscure ANSI features and disable GNU extensions
+   that might cause ANSI-compliant code to be miscompiled.  */
 
 extern int flag_ansi;
 
@@ -369,9 +378,6 @@ enum languages { lang_c, lang_cplusplus };
 #define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 1, (tree *)0) >= 0)
 #define DERIVED_FROM_P(PARENT, TYPE) (get_base_distance (PARENT, TYPE, 0, (tree *)0) != -1)
 \f
-enum conversion_type { ptr_conv, constptr_conv, int_conv,
-                      real_conv, last_conversion_type };
-
 /* Statistics show that while the GNU C++ compiler may generate
    thousands of different types during a compilation run, it
    generates relatively few (tens) of classtypes.  Because of this,
@@ -492,7 +498,6 @@ struct lang_type
   union tree_node *friend_classes;
 
   char *mi_matrix;
-  union tree_node *conversions[last_conversion_type];
 
   union tree_node *rtti;
 
@@ -657,6 +662,12 @@ struct lang_type
 /* List of lists of member functions defined in this class.  */
 #define CLASSTYPE_METHOD_VEC(NODE) TYPE_METHODS(NODE)
 
+/* The first type conversion operator in the class (the others can be
+   searched with TREE_CHAIN), or the first non-constructor function if
+   there are no type conversion operators.  */
+#define CLASSTYPE_FIRST_CONVERSION(NODE) \
+  TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), 1)
+
 /* Pointer from any member function to the head of the list of
    member functions of the type that member function belongs to.  */
 #define CLASSTYPE_BASELINK_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->baselink_vec)
@@ -807,12 +818,6 @@ struct lang_type
    a type is derived from another or not.  */
 #define CLASSTYPE_MI_MATRIX(NODE) (TYPE_LANG_SPECIFIC(NODE)->mi_matrix)
 
-/* If there is exactly one conversion to a non-void, non-const pointer type,
-   remember that here.  If there are more than one, put
-   `error_mark_node' here.  If there are none, this holds NULL_TREE.  */
-#define CLASSTYPE_CONVERSION(NODE,KIND) \
-  (TYPE_LANG_SPECIFIC(NODE)->conversions[(int) KIND])
-
 /* Say whether this node was declared as a "class" or a "struct".  */
 #define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
 /* whether this can be globalized.  */
@@ -2243,6 +2248,7 @@ extern void print_search_statistics               PROTO((void));
 extern void init_search_processing             PROTO((void));
 extern void reinit_search_statistics           PROTO((void));
 extern tree current_scope                      PROTO((void));
+extern tree lookup_conversions                 PROTO((tree));
 
 /* in sig.c */
 extern tree build_signature_pointer_type       PROTO((tree, int, int));
index 4883e7b..c42cb1a 100644 (file)
@@ -518,6 +518,18 @@ build_up_reference (type, arg, flags, checkconst)
                    build_up_reference (type, TREE_OPERAND (targ, 2),
                                        LOOKUP_PROTECT, checkconst));
 
+      /* Undo the folding... */
+    case MIN_EXPR:
+    case MAX_EXPR:
+      return build (COND_EXPR, type,
+                   build (TREE_CODE (targ) == MIN_EXPR ? LT_EXPR : GT_EXPR,
+                          boolean_type_node, TREE_OPERAND (targ, 0),
+                          TREE_OPERAND (targ, 1)),
+                   build_up_reference (type, TREE_OPERAND (targ, 0),
+                                       LOOKUP_PROTECT, checkconst),
+                   build_up_reference (type, TREE_OPERAND (targ, 1),
+                                       LOOKUP_PROTECT, checkconst));
+
     case WITH_CLEANUP_EXPR:
       return build (WITH_CLEANUP_EXPR, type,
                    build_up_reference (type, TREE_OPERAND (targ, 0),
@@ -666,11 +678,10 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
       if (form == REFERENCE_TYPE)
        {
          tree type = TREE_TYPE (expr);
-         tree tmp = copy_node (expr);
-         TREE_TYPE (tmp) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
-         rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), tmp,
+         TREE_TYPE (expr) = build_pointer_type (TREE_TYPE (type));
+         rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), expr,
                             convtype, flags);
-         TREE_TYPE (tmp) = type;
+         TREE_TYPE (expr) = type;
          TREE_TYPE (rval) = reftype;
          return rval;
        }
@@ -1487,14 +1498,8 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
 
    If (FOR_SURE & 1) is non-zero, then we allow this type conversion
    to take place immediately.  Otherwise, we build a SAVE_EXPR
-   which can be evaluated if the results are ever needed.
+   which can be evaluated if the results are ever needed.  */
 
-   If FOR_SURE >= 2, then we only look for exact conversions.
-
-   TYPE may be a reference type, in which case we first look
-   for something that will convert to a reference type.  If
-   that fails, we will try to look for something of the
-   reference's target type, and then return a reference to that.  */
 tree
 build_type_conversion (code, xtype, expr, for_sure)
      enum tree_code code;
@@ -1502,14 +1507,10 @@ build_type_conversion (code, xtype, expr, for_sure)
      int for_sure;
 {
   /* C++: check to see if we can convert this aggregate type
-     into the required scalar type.  */
-  tree type, type_default;
-  tree typename = build_typename_overload (xtype), *typenames;
-  int n_variants = 0;
-  tree basetype, save_basetype;
-  tree rval;
-  int exact_conversion = for_sure >= 2;
-  for_sure &= 1;
+     into the required type.  */
+  tree basetype;
+  tree conv;
+  tree winner = NULL_TREE;
 
   if (expr == error_mark_node)
     return error_mark_node;
@@ -1518,313 +1519,42 @@ build_type_conversion (code, xtype, expr, for_sure)
   if (TREE_CODE (basetype) == REFERENCE_TYPE)
     basetype = TREE_TYPE (basetype);
 
-  if (TYPE_PTRMEMFUNC_P (basetype) && TREE_CODE (xtype) == BOOLEAN_TYPE)
-    {
-      /* We convert a pointer to member function into a boolean,
-        by just checking the index value, for == 0, we want false, for
-        != 0, we want true.  */
-      return convert (xtype, build_component_ref (expr, index_identifier, 0, 0));
-    }
-
   basetype = TYPE_MAIN_VARIANT (basetype);
   if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype))
     return NULL_TREE;
 
-  if (TREE_CODE (xtype) == POINTER_TYPE
-      || TREE_CODE (xtype) == REFERENCE_TYPE)
-    {
-      /* Prepare to match a variant of this type.  */
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype));
-      for (n_variants = 0; type; type = TYPE_NEXT_VARIANT (type))
-       n_variants++;
-      typenames = (tree *)alloca (n_variants * sizeof (tree));
-      for (n_variants = 0, type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype));
-          type; n_variants++, type = TYPE_NEXT_VARIANT (type))
-       {
-         if (type == TREE_TYPE (xtype))
-           typenames[n_variants] = typename;
-         else if (TREE_CODE (xtype) == POINTER_TYPE)
-           typenames[n_variants] = build_typename_overload (build_pointer_type (type));
-         else
-           typenames[n_variants] = build_typename_overload (build_reference_type (type));
-       }
-    }
-
-  save_basetype = basetype;
-  type = xtype;
-
-  while (TYPE_HAS_CONVERSION (basetype))
-    {
-      int i;
-      if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
-       return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
-      for (i = 0; i < n_variants; i++)
-       if (typenames[i] != typename
-           && lookup_fnfields (TYPE_BINFO (basetype), typenames[i], 0))
-         return build_type_conversion_1 (xtype, basetype, expr, typenames[i], for_sure);
-
-      if (TYPE_BINFO_BASETYPES (basetype))
-       basetype = TYPE_BINFO_BASETYPE (basetype, 0);
-      else
-       break;
-    }
-
-  if (TREE_CODE (type) == REFERENCE_TYPE)
-    {
-#if 0
-      /* Only reference variable initializations can use a temporary; this
-         must be handled elsewhere (like convert_to_reference and
-         compute_conversion_costs).  */
-
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      typename = build_typename_overload (type);
-      basetype = save_basetype;
-
-      /* May need to build a temporary for this.  */
-      while (TYPE_HAS_CONVERSION (basetype))
-       {
-         if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
-           {
-             int flags;
-
-             if (for_sure == 0)
-               flags = LOOKUP_PROTECT|LOOKUP_ONLYCONVERTING;
-             else
-               flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING;
-             rval = build_method_call (expr,
-                                       constructor_name_full (typename),
-                                       NULL_TREE, NULL_TREE, flags);
-             if (rval == error_mark_node)
-               {
-                 if (for_sure == 0)
-                   return NULL_TREE;
-                 return error_mark_node;
-               }
-
-             return convert (xtype, rval);
-           }
-         if (TYPE_BINFO_BASETYPES (basetype))
-           basetype = TYPE_BINFO_BASETYPE (basetype, 0);
-         else
-           break;
-       }
-#endif
-      /* No free conversions for reference types, right?.  */
-      return NULL_TREE;
-    }
-
-  if (exact_conversion)
-    return NULL_TREE;
-
-  if (TREE_CODE (type) == BOOLEAN_TYPE)
-    {
-      tree as_int = build_type_conversion (code, long_long_unsigned_type_node, expr, 0);
-      tree as_ptr = build_type_conversion (code, ptr_type_node, expr, 0);
-      /* We are missing the conversion to pointer to member type. */
-      /* We are missing the conversion to floating type. */
-      if (as_int && as_ptr && for_sure)
-       {
-         cp_error ("ambiguous conversion from `%T' to `bool', can convert to integral type or pointer", TREE_TYPE (expr));
-         return error_mark_node;
-       }
-      if (as_int)
-       {
-         as_int = build_type_conversion (code, long_long_unsigned_type_node, expr, for_sure+exact_conversion*2);
-         return convert (xtype, as_int);
-       }
-      if (as_ptr)
-       {
-         as_ptr = build_type_conversion (code, ptr_type_node, expr, for_sure+exact_conversion*2);
-         return convert (xtype, as_ptr);
-       }
-      return NULL_TREE;
-    }
-
-  /* No perfect match found, try default.  */
-#if 0 /* This is wrong; there is no standard conversion from void* to
-         anything.  -jason */
-  if (code == CONVERT_EXPR && TREE_CODE (type) == POINTER_TYPE)
-    type_default = ptr_type_node;
-  else
-#endif
-  if (type == void_type_node)
-    return NULL_TREE;
-  else
-    {
-      tree tmp = default_conversion (build1 (NOP_EXPR, type, integer_zero_node));
-      if (tmp == error_mark_node)
-       return NULL_TREE;
-      type_default = TREE_TYPE (tmp);
-    }
-
-  basetype = save_basetype;
-
-  if (type_default != type)
-    {
-      type = type_default;
-      typename = build_typename_overload (type);
-
-      while (TYPE_HAS_CONVERSION (basetype))
-       {
-         if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
-           return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
-         if (TYPE_BINFO_BASETYPES (basetype))
-           basetype = TYPE_BINFO_BASETYPE (basetype, 0);
-         else
-           break;
-       }
-    }
-
-  if (TREE_CODE (type) == POINTER_TYPE && TYPE_READONLY (TREE_TYPE (type)))
-    {
-      /* Try converting to some other const pointer type and then using
-         standard conversions. */
-
-      while (TYPE_HAS_CONVERSION (basetype))
-       {
-         if (CLASSTYPE_CONVERSION (basetype, constptr_conv) != 0)
-           {
-             if (CLASSTYPE_CONVERSION (basetype, constptr_conv) == error_mark_node)
-               return error_mark_node;
-             typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, constptr_conv));
-             return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
-           }
-         if (TYPE_BINFO_BASETYPES (basetype))
-           basetype = TYPE_BINFO_BASETYPE (basetype, 0);
-         else
-           break;
-       }
-    }
-  if (TREE_CODE (type) == POINTER_TYPE)
-    {
-      /* Try converting to some other pointer type and then using standard
-        conversions.  */
-
-      while (TYPE_HAS_CONVERSION (basetype))
-       {
-         if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0)
-           {
-             if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node)
-               return error_mark_node;
-             typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv));
-             return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
-           }
-         if (TYPE_BINFO_BASETYPES (basetype))
-           basetype = TYPE_BINFO_BASETYPE (basetype, 0);
-         else
-           break;
-       }
-    }
-
-  /* Use the longer or shorter conversion that is appropriate.  Have
-     to check against 0 because the conversion may come from a baseclass.  */
-  if (TREE_CODE (type) == INTEGER_TYPE
-      && TYPE_HAS_INT_CONVERSION (basetype)
-      && CLASSTYPE_CONVERSION (basetype, int_conv) != 0
-      && CLASSTYPE_CONVERSION (basetype, int_conv) != error_mark_node)
-    {
-      typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, int_conv));
-      return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
-    }
+  /* Do we have an exact match?  */
+  {
+    tree typename = build_typename_overload (xtype);
+    if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
+      return build_type_conversion_1 (xtype, basetype, expr, typename,
+                                     for_sure);
+  }
 
-  if (TREE_CODE (type) == REAL_TYPE
-      && TYPE_HAS_REAL_CONVERSION (basetype)
-      && CLASSTYPE_CONVERSION (basetype, real_conv) != 0
-      && CLASSTYPE_CONVERSION (basetype, real_conv) != error_mark_node)
+  /* Nope; try looking for others.  */
+  for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
     {
-      /* Only accept using an operator double() if there isn't a conflicting
-        operator int().  */
-      if (TYPE_HAS_INT_CONVERSION (basetype))
-       {
-         if (for_sure)
-           {
-             cp_error ("two possible conversions for type `%T'", type);
-             return error_mark_node;
-           }
-         else
-           return NULL_TREE;
-       }
+      if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+       continue;
 
-      typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, real_conv));
-      return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
-    }
-
-  /* THESE ARE TOTAL KLUDGES.  */
-  /* Default promotion yields no new alternatives, try
-     conversions which are anti-default, such as
-
-     double -> float or int -> unsigned or unsigned -> long
-
-     */
-  if (type_default == type
-      && (INTEGRAL_TYPE_P (type) || TREE_CODE (type) == REAL_TYPE))
-    {
-      int not_again = 0;
-
-      if (type == double_type_node)
-       typename = build_typename_overload (float_type_node);
-      else if (type == integer_type_node)
-       typename = build_typename_overload (unsigned_type_node);
-      else if (type == unsigned_type_node)
-       typename = build_typename_overload (long_integer_type_node);
-
-    again:
-      basetype = save_basetype;
-      while (TYPE_HAS_CONVERSION (basetype))
-       {
-         if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
-           return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
-         if (TYPE_BINFO_BASETYPES (basetype))
-           basetype = TYPE_BINFO_BASETYPE (basetype, 0);
-         else
-           break;
-       }
-      if (! not_again)
+      if (can_convert (xtype, TREE_VALUE (conv)))
        {
-         if (type == integer_type_node)
+         if (winner)
            {
-             typename = build_typename_overload (long_integer_type_node);
-             not_again = 1;
-             goto again;
+             cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
+                       xtype);
+             cp_error ("  candidate conversion functions include `%T' and `%T'",
+                       TREE_VALUE (winner), TREE_VALUE (conv));
+             return NULL_TREE;
            }
          else
-           {
-             typename = build_typename_overload (integer_type_node);
-             not_again = 1;
-             goto again;
-           }
+           winner = conv;
        }
     }
 
-  /* Now, try C promotions...
-
-     float -> int
-     int -> float  */
-
-    basetype = save_basetype;
-    if (TREE_CODE (type) == REAL_TYPE)
-      type = integer_type_node;
-    else if (TREE_CODE (type) == INTEGER_TYPE)
-      if (TYPE_HAS_REAL_CONVERSION (basetype))
-       type = double_type_node;
-      else
-       return NULL_TREE;
-    else
-      return NULL_TREE;
-
-    typename = build_typename_overload (type);
-    while (TYPE_HAS_CONVERSION (basetype))
-      {
-       if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
-         {
-           rval = build_type_conversion_1 (xtype, basetype, expr, typename, for_sure);
-           return rval;
-         }
-       if (TYPE_BINFO_BASETYPES (basetype))
-         basetype = TYPE_BINFO_BASETYPE (basetype, 0);
-       else
-         break;
-      }
+  if (winner)
+    return build_type_conversion_1 (xtype, basetype, expr,
+                                   TREE_PURPOSE (winner), for_sure);
 
   return NULL_TREE;
 }
index 8a6c6ea..a6d7e3f 100644 (file)
@@ -49,6 +49,8 @@ extern int current_class_depth;
 
 extern tree cleanups_this_call;
 
+extern tree static_ctors, static_dtors;
+
 /* Stack of places to restore the search obstack back to.  */
    
 /* Obstack used for remembering local class declarations (like
@@ -94,7 +96,11 @@ static struct stack_level *decl_stack;
 #endif
 
 #ifndef BOOL_TYPE_SIZE
+#ifdef SLOW_BYTE_ACCESS
 #define BOOL_TYPE_SIZE BITS_PER_WORD
+#else
+#define BOOL_TYPE_SIZE BITS_PER_UNIT
+#endif
 #endif
 
 /* We let tm.h override the types used here, to handle trivial differences
@@ -428,7 +434,8 @@ extern int flag_no_builtin;
 
 extern int flag_no_nonansi_builtin;
 
-/* Nonzero means disable GNU extensions.  */
+/* Nonzero means enable obscure ANSI features and disable GNU extensions
+   that might cause ANSI-compliant code to be miscompiled.  */
 
 extern int flag_ansi;
 
@@ -1638,27 +1645,25 @@ static void
 set_nested_typename (decl, classname, name, type)
      tree decl, classname, name, type;
 {
+  char *buf;
   my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
-  if (classname != NULL_TREE)
-    {
-      char *buf;
-      my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
-      my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
-      buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
-                            + IDENTIFIER_LENGTH (name));
-      sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
-              IDENTIFIER_POINTER (name));
-      DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
-      TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
-
-      /* This is a special usage of IDENTIFIER_TYPE_VALUE which have no
-        correspondence in any binding_level.  This is ok since the
-        DECL_NESTED_TYPENAME is just a convenience identifier whose
-        IDENTIFIER_TYPE_VALUE will remain constant from now on.  */
-      SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type);
-    }
-  else
-    DECL_NESTED_TYPENAME (decl) = name;
+  if (classname == NULL_TREE)
+    classname = get_identifier ("");
+
+  my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 137);
+  my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 138);
+  buf = (char *) alloca (4 + IDENTIFIER_LENGTH (classname)
+                        + IDENTIFIER_LENGTH (name));
+  sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
+          IDENTIFIER_POINTER (name));
+  DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
+  TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
+
+  /* This is a special usage of IDENTIFIER_TYPE_VALUE which have no
+     correspondence in any binding_level.  This is ok since the
+     DECL_NESTED_TYPENAME is just a convenience identifier whose
+     IDENTIFIER_TYPE_VALUE will remain constant from now on.  */
+  SET_IDENTIFIER_TYPE_VALUE (DECL_NESTED_TYPENAME (decl), type);
 }
 
 /* Pop off extraneous binding levels left over due to syntax errors.  */
@@ -1743,11 +1748,13 @@ pushtag (name, type, globalize)
         context = current_scope ();
       if (context)
        c_decl = TREE_CODE (context) == FUNCTION_DECL
-         ? context : TYPE_NAME (context);
+         ? context : TYPE_MAIN_DECL (context);
 
+#if 0
       /* Record the identifier as the type's name if it has none.  */
       if (TYPE_NAME (type) == NULL_TREE)
         TYPE_NAME (type) = name;
+#endif
       
       /* Do C++ gratuitous typedefing.  */
       if (IDENTIFIER_TYPE_VALUE (name) != type)
@@ -1784,14 +1791,11 @@ pushtag (name, type, globalize)
              else
                d = TYPE_NAME (d);
 
+             TYPE_NAME (type) = d;
+
              /* If it is anonymous, then we are called from pushdecl,
-                and we don't want to infinitely recurse.  Also, if the
-                name is already in scope, we don't want to push it
-                again--pushdecl is only for pushing new decls.  */
-             if (! ANON_AGGRNAME_P (name)
-                 && TYPE_NAME (type)
-                 && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL
-                     || lookup_name (name, 1) != TYPE_NAME (type)))
+                and we don't want to infinitely recurse.  */
+             if (! ANON_AGGRNAME_P (name))
                {
                  if (b->parm_flag == 2)
                    d = pushdecl_class_level (d);
@@ -1815,6 +1819,9 @@ pushtag (name, type, globalize)
                  DECL_IGNORED_P (d) = 1;
                }
 #endif /* DWARF_DEBUGGING_INFO */
+
+             TYPE_NAME (type) = d;
+
              /* Make sure we're in this type's scope when we push the
                 decl for a template, otherwise class_binding_level will
                 be NULL and we'll end up dying inside of
@@ -1830,11 +1837,10 @@ pushtag (name, type, globalize)
              if (ANON_AGGRNAME_P (name))
                DECL_IGNORED_P (d) = 1;
            }
-         TYPE_NAME (type) = d;
 
          if (context == NULL_TREE)
            /* Non-nested class.  */
-           DECL_NESTED_TYPENAME (d) = name;
+           set_nested_typename (d, NULL_TREE, name, type);
          else if (context && TREE_CODE (context) == FUNCTION_DECL)
            {
              /* Function-nested class.  */
@@ -2036,7 +2042,9 @@ decls_match (newdecl, olddecl)
       else if (TREE_TYPE (newdecl) == NULL_TREE)
        types_match = 0;
       else
-       types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1);
+       types_match = (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 1)
+                      && TREE_READONLY (newdecl) == TREE_READONLY (olddecl)
+                      && TREE_THIS_VOLATILE (newdecl) == TREE_THIS_VOLATILE (olddecl));
     }
 
   return types_match;
@@ -2226,16 +2234,6 @@ duplicate_decls (newdecl, olddecl)
            return 0;
        }
 
-      if (olddecl == wchar_decl_node)
-       {
-         if (pedantic && ! DECL_IN_SYSTEM_HEADER (newdecl))
-           cp_pedwarn ("redeclaration of wchar_t as `%T'",
-                       TREE_TYPE (newdecl));
-
-         /* Throw away the redeclaration.  */
-         return 1;
-       }
-
       /* Already complained about this, so don't do so again.  */
       else if (current_class_type == NULL_TREE
          || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
@@ -2281,6 +2279,39 @@ duplicate_decls (newdecl, olddecl)
                        DECL_LANGUAGE (newdecl));
            }
        }
+
+      if (TREE_CODE (olddecl) == FUNCTION_DECL)
+       {
+         tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
+         tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
+         int i = 1;
+
+         if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
+           t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
+       
+         for (; t1 && t1 != void_list_node;
+              t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
+           if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
+             {
+               if (simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
+                 {
+                   if (pedantic)
+                     {
+                       cp_pedwarn ("default argument given for parameter %d of `%#D'",
+                                   i, newdecl);
+                       cp_pedwarn_at ("after previous specification in `%#D'",
+                                      olddecl);
+                     }
+                 }
+               else
+                 {
+                   cp_error ("default argument given for parameter %d of `%#D'",
+                             i, newdecl);
+                   cp_error_at ("conflicts with previous specification in `%#D'",
+                                olddecl);
+                 }
+             }
+       }
     }
 
   /* If new decl is `static' and an `extern' was seen previously,
@@ -2306,6 +2337,8 @@ duplicate_decls (newdecl, olddecl)
        DECL_NEXT_METHOD (newdecl) = DECL_NEXT_METHOD (olddecl);
       if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
        DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
+      DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
+      DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
     }
 
   /* Deal with C++: must preserve virtual function table size.  */
@@ -2358,13 +2391,10 @@ duplicate_decls (newdecl, olddecl)
     {
       /* Automatically handles default parameters.  */
       tree oldtype = TREE_TYPE (olddecl);
-      /* Merge the data types specified in the two decls.  */
-      tree newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+      tree newtype;
 
-      /* Make sure we put the new type in the same obstack as the old ones.
-        If the old types are not both in the same obstack, use the permanent
-        one.  */
-      if (oldtype && TYPE_OBSTACK (oldtype) == TYPE_OBSTACK (newtype))
+      /* Make sure we put the new type in the same obstack as the old one.  */
+      if (oldtype)
        push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
       else
        {
@@ -2372,6 +2402,9 @@ duplicate_decls (newdecl, olddecl)
          end_temporary_allocation ();
        }
 
+      /* Merge the data types specified in the two decls.  */
+      newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
+
       if (TREE_CODE (newdecl) == VAR_DECL)
        DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
       /* Do this after calling `common_type' so that default
@@ -2703,6 +2736,14 @@ pushdecl (x)
                   && ! DECL_TEMPLATE_IS_CLASS (x)))
              && is_overloaded_fn (t))
            /* don't do anything just yet */;
+         else if (t == wchar_decl_node)
+           {
+             if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
+               cp_pedwarn ("redeclaration of wchar_t as `%T'", TREE_TYPE (x));
+
+             /* Throw away the redeclaration.  */
+             return t;
+           }
          else if (TREE_CODE (t) != TREE_CODE (x))
            {
              if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
@@ -2796,9 +2837,8 @@ pushdecl (x)
            }
          my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 140);
 
-         if (DECL_NAME (name) && !DECL_NESTED_TYPENAME (name))
-           set_nested_typename (x, current_class_name,
-                                DECL_NAME (name), type);
+         if (! DECL_NESTED_TYPENAME (x))
+           set_nested_typename (x, current_class_name, DECL_NAME (x), type);
 
          if (type != error_mark_node
              && TYPE_NAME (type)
@@ -2856,11 +2896,11 @@ pushdecl (x)
          if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && DECL_PUBLIC (x))
            TREE_PUBLIC (name) = 1;
 
-         /* Don't install a TYPE_DECL if we already have another
-            sort of _DECL with that name.  */
+         /* Don't install an artificial TYPE_DECL if we already have
+            another _DECL with that name.  */
          if (TREE_CODE (x) != TYPE_DECL
              || t == NULL_TREE
-             || TREE_CODE (t) == TYPE_DECL)
+             || ! DECL_ARTIFICIAL (x))
            IDENTIFIER_GLOBAL_VALUE (name) = x;
 
          /* Don't forget if the function was used via an implicit decl.  */
@@ -2892,8 +2932,15 @@ pushdecl (x)
          tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
          tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
 
-         b->shadowed = tree_cons (name, oldlocal, b->shadowed);
-         IDENTIFIER_LOCAL_VALUE (name) = x;
+         /* Don't install an artificial TYPE_DECL if we already have
+            another _DECL with that name.  */
+         if (TREE_CODE (x) != TYPE_DECL
+             || t == NULL_TREE
+             || ! DECL_ARTIFICIAL (x))
+           {
+             b->shadowed = tree_cons (name, oldlocal, b->shadowed);
+             IDENTIFIER_LOCAL_VALUE (name) = x;
+           }
 
          /* If this is a TYPE_DECL, push it into the type value slot.  */
          if (TREE_CODE (x) == TYPE_DECL)
@@ -2968,11 +3015,25 @@ pushdecl (x)
              if (warnstring)
                warning (warnstring, IDENTIFIER_POINTER (name));
            }
+       }
 
-         /* If storing a local value, there may already be one (inherited).
-            If so, record it for restoration when this binding level ends.  */
-         if (oldlocal != NULL_TREE)
-           b->shadowed = tree_cons (name, oldlocal, b->shadowed);
+      if (TREE_CODE (x) == FUNCTION_DECL)
+       {
+         /* This is probably the wrong place to check this, but it has to
+             come after the call to duplicate_decls.  */
+         tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
+         int saw_def = 0, i = 1;
+         for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
+           {
+             if (TREE_PURPOSE (arg))
+               saw_def = 1;
+             else if (saw_def)
+               {
+                 cp_error ("default argument missing for parameter %d of `%#D'",
+                           i, x);
+                 break;
+               }
+           }
        }
 
       /* Keep count of variables in this level with incomplete type.  */
@@ -3168,6 +3229,10 @@ push_class_level_binding (name, x)
      tree name;
      tree x;
 {
+  if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+      && purpose_member (name, class_binding_level->class_shadowed))
+    return;
+
   maybe_push_cache_obstack ();
   class_binding_level->class_shadowed
       = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
@@ -3251,13 +3316,7 @@ push_overloaded_decl (decl, forgettable)
        old = TREE_OPERAND (old, 0);
       else
 #endif
-      if (TREE_CODE (old) == VAR_DECL)
-       {
-         cp_error_at ("previous non-function declaration `%#D'", old);
-         cp_error ("conflicts with function declaration `%#D'", decl);
-         return error_mark_node;
-       }
-      else if (TREE_CODE (old) == TYPE_DECL)
+      if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
        {
          tree t = TREE_TYPE (old);
          if (IS_AGGR_TYPE (t) && warn_shadow)
@@ -3272,6 +3331,12 @@ push_overloaded_decl (decl, forgettable)
            if (decl == tmp || duplicate_decls (decl, tmp))
              return tmp;
        }
+      else
+       {
+         cp_error_at ("previous non-function declaration `%#D'", old);
+         cp_error ("conflicts with function declaration `%#D'", decl);
+         return error_mark_node;
+       }
     }
 
   if (old || TREE_CODE (decl) == TEMPLATE_DECL)
@@ -3386,18 +3451,6 @@ redeclaration_error_message (newdecl, olddecl)
          else
            return "redefinition of `%#D'";
        }
-
-      {
-       tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
-       tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
-
-       if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
-         t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
-       
-       for (; t1; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
-         if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
-           return "duplicate default arguments given for `%#D'";
-      }
       return 0;
     }
   else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
@@ -3535,6 +3588,9 @@ define_label (filename, line, name)
       decl = lookup_label (name);
     }
 
+  if (name == get_identifier ("wchar_t"))
+    cp_pedwarn ("label named wchar_t");
+
   if (DECL_INITIAL (decl) != NULL_TREE)
     {
       cp_error ("duplicate label `%D'", decl);
@@ -3866,9 +3922,9 @@ lookup_nested_type (type, context)
          }
          break;
        case FUNCTION_DECL:
-         return TYPE_IDENTIFIER (type) ?
-           lookup_name (TYPE_IDENTIFIER (type), 1) : NULL_TREE;
-         break;
+         if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
+           return lookup_name (TYPE_IDENTIFIER (type), 1);
+         return NULL_TREE;
        default:
          my_friendly_abort (12);
        }
@@ -3893,43 +3949,50 @@ lookup_name_real (name, prefer_type, nonclass)
 {
   register tree val;
   int yylex = 0;
+  tree from_obj = NULL_TREE;
 
   if (prefer_type == -2)
     {
       extern int looking_for_typename;
+      tree type;
 
       yylex = 1;
       prefer_type = looking_for_typename;
+
+      if (got_scope)
+       type = got_scope;
+      else
+       type = got_object;
       
-      if (got_scope != NULL_TREE)
+      if (type)
        {
-         if (got_scope == error_mark_node)
+         if (type == error_mark_node)
            return error_mark_node;
-         else if (got_scope == void_type_node)
+         else if (type == void_type_node)
            val = IDENTIFIER_GLOBAL_VALUE (name);
-         else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM
+         else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
                   /* TFIXME -- don't do this for UPTs in new model.  */
-                  || TREE_CODE (got_scope) == UNINSTANTIATED_P_TYPE)
+                  || TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
            {
              if (prefer_type > 0)
-               val = create_nested_upt (got_scope, name);
+               val = create_nested_upt (type, name);
              else
                val = NULL_TREE;
            }
-         else if (! IS_AGGR_TYPE (got_scope))
+         else if (! IS_AGGR_TYPE (type))
            /* Someone else will give an error about this if needed. */
            val = NULL_TREE;
-         else if (TYPE_BEING_DEFINED (got_scope))
+         else if (TYPE_BEING_DEFINED (type))
            {
              val = IDENTIFIER_CLASS_VALUE (name);
-             if (val && DECL_CONTEXT (val) != got_scope)
+             if (val && DECL_CONTEXT (val) != type)
                {
                  struct binding_level *b = class_binding_level;
                  for (val = NULL_TREE; b; b = b->level_chain)
                    {
                      tree t = purpose_member (name, b->class_shadowed);
                      if (t && TREE_VALUE (t)
-                         && DECL_CONTEXT (TREE_VALUE (t)) == got_scope)
+                         && DECL_CONTEXT (TREE_VALUE (t)) == type)
                        {
                          val = TREE_VALUE (t);
                          break;
@@ -3937,16 +4000,23 @@ lookup_name_real (name, prefer_type, nonclass)
                    }
                }
              if (val == NULL_TREE
-                 && CLASSTYPE_LOCAL_TYPEDECLS (got_scope))
-               val = lookup_field (got_scope, name, 0, 1);
+                 && CLASSTYPE_LOCAL_TYPEDECLS (type))
+               val = lookup_field (type, name, 0, 1);
            }
-         else if (got_scope == current_class_type)
+         else if (type == current_class_type)
            val = IDENTIFIER_CLASS_VALUE (name);
          else
-           val = lookup_field (got_scope, name, 0, 0);
-
-         goto done;
+           val = lookup_field (type, name, 0, prefer_type);
        }
+      else
+       val = NULL_TREE;
+
+      if (got_scope)
+       goto done;
+
+      /* This special lookup only applies to types.  */
+      else if (got_object && val && TREE_CODE (val) == TYPE_DECL)
+       from_obj = val;
     }
     
   if (current_binding_level != global_binding_level
@@ -3980,16 +4050,20 @@ lookup_name_real (name, prefer_type, nonclass)
  done:
   if (val)
     {
+      if (from_obj && from_obj != val)
+       cp_error ("lookup in the scope of `%#T' does not match lookup in the current scope",
+                 got_object);
+
       if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
          || TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
-       return val;
-
-      if (IDENTIFIER_HAS_TYPE_VALUE (name))
-       return TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
-
-      if (TREE_TYPE (val) == error_mark_node)
-       return error_mark_node;
+       ;
+      else if (IDENTIFIER_HAS_TYPE_VALUE (name))
+       val = TYPE_NAME (IDENTIFIER_TYPE_VALUE (name));
+      else if (TREE_TYPE (val) == error_mark_node)
+       val = error_mark_node;
     }
+  else if (from_obj)
+    val = from_obj;
 
   return val;
 }
@@ -4031,7 +4105,7 @@ lookup_name_current_level (name)
       while (1)
        {
          for (t = b->names; t; t = TREE_CHAIN (t))
-           if (DECL_NAME (t) == name)
+           if (DECL_NAME (t) == name || DECL_ASSEMBLER_NAME (t) == name)
              goto out;
          if (b->keep == 2)
            b = b->level_chain;
@@ -4207,13 +4281,19 @@ init_decl_processing ()
   int wchar_type_size;
   tree temp;
   tree array_domain_type;
+  extern int flag_strict_prototype;
 
   /* Have to make these distinct before we try using them.  */
   lang_name_cplusplus = get_identifier ("C++");
   lang_name_c = get_identifier ("C");
 
-  if (flag_ansi || pedantic)
-    strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
+  if (flag_strict_prototype == 2)
+    {
+      if (pedantic)
+       strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
+    }
+  else
+    strict_prototypes_lang_c = flag_strict_prototype;
 
   /* Initially, C.  */
   current_lang_name = lang_name_c;
@@ -5629,8 +5709,9 @@ grok_reference_init (decl, type, init, cleanupp)
 
   if (init == NULL_TREE)
     {
-      if (DECL_LANG_SPECIFIC (decl) == 0
-         || DECL_IN_AGGR_P (decl) == 0)
+      if ((DECL_LANG_SPECIFIC (decl) == 0
+          || DECL_IN_AGGR_P (decl) == 0)
+         && ! DECL_THIS_EXTERN (decl))
        {
          cp_error ("`%D' declared as reference but not initialized", decl);
          if (TREE_CODE (decl) == VAR_DECL)
@@ -6530,12 +6611,24 @@ complete_array_type (type, initial_value, do_default)
       /* Note MAXINDEX  is really the maximum index,
         one less than the size.  */
       if (TREE_CODE (initial_value) == STRING_CST)
-       maxindex = build_int_2 (TREE_STRING_LENGTH (initial_value) - 1, 0);
+       {
+         int eltsize
+           = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
+         maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
+                                  / eltsize) - 1, 0);
+       }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
-         register int nelts
-           = list_length (CONSTRUCTOR_ELTS (initial_value));
-         maxindex = build_int_2 (nelts - 1, - (nelts == 0));
+         tree elts = CONSTRUCTOR_ELTS (initial_value);
+         maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+         for (; elts; elts = TREE_CHAIN (elts))
+           {
+             if (TREE_PURPOSE (elts))
+               maxindex = TREE_PURPOSE (elts);
+             else
+               maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
+           }
+         maxindex = copy_node (maxindex);
        }
       else
        {
@@ -7281,6 +7374,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
   if (funcdef_flag && innermost_code != CALL_EXPR)
     return 0;
 
+  if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
+      && innermost_code != CALL_EXPR
+      && ! (ctype && declspecs == NULL_TREE))
+    {
+      cp_error ("declaration of `%D' as non-function", dname);
+      return void_type_node;
+    }
+
   /* Anything declared one level down from the top level
      must be one of the parameters of a function
      (because the body is at least two levels down).  */
@@ -7361,8 +7462,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                {
                  if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
                    {
-                     if (pedantic && flag_ansi)
-                       pedwarn ("duplicate `long'");
+                     if (pedantic && ! in_system_header)
+                       pedwarn ("ANSI C++ does not support `long long'");
                      else if (longlong)
                        error ("`long long long' is too long for GCC");
                      else
@@ -7468,7 +7569,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
     }
   else if (return_type == return_conversion)
     {
-      if (comp_target_types (type, ctor_return_type, 1) == 0)
+      if (comptypes (type, ctor_return_type, 1) == 0)
        cp_error ("operator `%T' declared to return `%T'",
                  ctor_return_type, type);
       else
@@ -8022,7 +8123,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                  }
                if (TREE_READONLY_DECL_P (size))
                  size = decl_constant_value (size);
-               if (flag_ansi && integer_zerop (size))
+               if (pedantic && integer_zerop (size))
                  cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname);
                if (TREE_CONSTANT (size))
                  {
@@ -8037,7 +8138,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                  }
                else
                  {
-                   if (flag_ansi)
+                   if (pedantic)
                      {
                        if (dname)
                          cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
@@ -8384,9 +8485,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                  && (constp || volatilep))
                {
                  if (constp)
-                   warning ("discarding `const' applied to a reference");
+                   pedwarn ("discarding `const' applied to a reference");
                  if (volatilep)
-                   warning ("discarding `volatile' applied to a reference");
+                   pedwarn ("discarding `volatile' applied to a reference");
                  constp = volatilep = 0;
                }
            }
@@ -8956,7 +9057,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                   initialize the named nonstatic member....  This (or an
                   initializer list) is the only way to initialize
                   nonstatic const and reference members.  */
-               else if (flag_ansi || ! constp)
+               else if (pedantic || ! constp)
                  cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
                              constp ? "const member" : "member", declarator);
              }
@@ -9103,7 +9204,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
            if (RIDBIT_SETP (RID_EXTERN, specbits))
              {
                current_extern_inline = 1;
-               if (flag_ansi)
+               if (pedantic)
                  pedwarn ("ANSI C++ does not permit `extern inline'");
              }
          }
@@ -9450,12 +9551,19 @@ grokparms (first_parm, funcdef_flag)
                        }
                      else
                        init = require_instantiated_type (type, init, integer_zero_node);
+
+                     init = convert_for_initialization
+                       (NULL_TREE, type, init, LOOKUP_NORMAL,
+                        "argument passing", 0, 0);
                    }
+#if 0 /* This is too early to check; trailing parms might be merged in by
+        duplicate_decls.  */
                  else if (any_init)
                    {
                      error ("all trailing parameters must have default arguments");
                      any_error = 1;
                    }
+#endif
                }
              else
                init = NULL_TREE;
@@ -11042,7 +11150,7 @@ store_return_init (return_id, init)
 {
   tree decl = DECL_RESULT (current_function_decl);
 
-  if (flag_ansi)
+  if (pedantic)
     /* Give this error as many times as there are occurrences,
        so that users can use Emacs compilation buffers to find
        and fix all such places.  */
@@ -11539,45 +11647,11 @@ finish_function (lineno, call_poplevel, nested)
   /* So we can tell if jump_optimize sets it to 1.  */
   can_reach_end = 0;
 
-  if (DECL_EXTERNAL (fndecl)
-      /* This function is just along for the ride.  If we can make
-        it inline, that's great.  Otherwise, just punt it.  */
-      && (DECL_INLINE (fndecl) == 0
-         || flag_no_inline
-         || function_cannot_inline_p (fndecl)
-         /* ??? Compensate for Sun brain damage in dealing with
-            data segments of PIC code.  */
-         || (flag_pic
-             && (DECL_CONSTRUCTOR_P (fndecl)
-                 || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
-             && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype)))))
-
-    {
-      extern int rtl_dump_and_exit;
-      int old_rtl_dump_and_exit = rtl_dump_and_exit;
-      int inline_spec = DECL_INLINE (fndecl);
-
-      /* This throws away the code for FNDECL.  */
-      rtl_dump_and_exit = 1;
-      /* This throws away the memory of the code for FNDECL.  */
-      if (flag_no_inline)
-       DECL_INLINE (fndecl) = 0;
-      rest_of_compilation (fndecl);
-      rtl_dump_and_exit = old_rtl_dump_and_exit;
-      DECL_INLINE (fndecl) = inline_spec;
-    }
-  else
-    {
-      /* Run the optimizers and output the assembler code for this
-         function.  */
-      rest_of_compilation (fndecl);
-    }
+  /* Run the optimizers and output the assembler code for this function.  */
+  rest_of_compilation (fndecl);
 
-  if (DECL_INLINE (fndecl) && !TREE_ASM_WRITTEN (fndecl)
-      && DECL_DEFER_OUTPUT (fndecl))
-    {
-      mark_inline_for_output (fndecl);
-    }
+  if (DECL_DEFER_OUTPUT (fndecl))
+    mark_inline_for_output (fndecl);
 
   if (ctype && TREE_ASM_WRITTEN (fndecl))
     note_debug_info_needed (ctype);
@@ -11628,6 +11702,11 @@ finish_function (lineno, call_poplevel, nested)
        DECL_ARGUMENTS (fndecl) = NULL_TREE;
     }
 
+  if (DECL_STATIC_CONSTRUCTOR (fndecl))
+    static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
+  if (DECL_STATIC_DESTRUCTOR (fndecl))
+    static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
+
   /* Let the error reporting routines know that we're outside a function.  */
   current_function_decl = NULL_TREE;
   named_label_uses = NULL_TREE;
index df2b119..127e6b2 100644 (file)
@@ -64,6 +64,10 @@ static int global_temp_name_counter;
 /* Flag used when debugging spew.c */
 
 extern int spew_debug;
+
+/* Functions called along with real static constructors and destructors.  */
+
+tree static_ctors, static_dtors;
 \f
 /* C (and C++) language-specific option variables.  */
 
@@ -80,6 +84,10 @@ int flag_short_double;
 
 int flag_no_asm;
 
+/* Nonzero means don't recognize any extension keywords.  */
+
+int flag_no_gnu_keywords;
+
 /* Nonzero means don't recognize the non-ANSI builtin functions.  */
 
 int flag_no_builtin;
@@ -99,11 +107,12 @@ int flag_signed_bitfields = 1;
 
 /* Nonzero means handle `#ident' directives.  0 means ignore them.  */
 
-int flag_no_ident = 0;
+int flag_no_ident;
 
-/* Nonzero means disable GNU extensions.  */
+/* Nonzero means enable obscure ANSI features and disable GNU extensions
+   that might cause ANSI-compliant code to be miscompiled.  */
 
-int flag_ansi = 0;
+int flag_ansi;
 
 /* Nonzero means do emit exported implementations of functions even if
    they can be inlined.  */
@@ -113,13 +122,13 @@ int flag_implement_inlines = 1;
 /* Nonzero means do emit exported implementations of templates, instead of
    multiple static copies in each file that needs a definition. */
 
-int flag_external_templates = 0;
+int flag_external_templates;
 
 /* Nonzero means that the decision to emit or not emit the implementation of a
    template depends on where the template is instantiated, rather than where
    it is defined.  */
 
-int flag_alt_external_templates = 0;
+int flag_alt_external_templates;
 
 /* Nonzero means that implicit instantiations will be emitted if needed.  */
 
@@ -139,7 +148,7 @@ int warn_ctor_dtor_privacy = 1;
 
    Also causes output of vtables to be controlled by whether
    we seen the class's first non-inline virtual function. */
-int flag_vtable_thunks = 0;
+int flag_vtable_thunks;
 
 /* Nonzero means give string constants the type `const char *'
    to get extra warnings from them.  These warnings will be too numerous
@@ -198,7 +207,7 @@ int warn_conversion;
 
 /* Warn if adding () is suggested.  */
 
-int warn_parentheses = 1;
+int warn_parentheses;
 
 /* Non-zero means warn in function declared in derived class has the
    same name as a virtual in the base class, but fails to match the
@@ -229,6 +238,7 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
 /* Nonzero for -fno-strict-prototype switch: do not consider empty
    argument prototype to mean function takes no arguments.  */
 
+int flag_strict_prototype = 2;
 int strict_prototype = 1;
 int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus = 1;
 
@@ -303,7 +313,7 @@ int flag_gc;
 
 /* Controls whether compiler generates 'type descriptor' that give
    run-time type information.  */
-int flag_rtti = 0;
+int flag_rtti;
 
 /* Nonzero if we wish to output cross-referencing information
    for the GNU class browser.  */
@@ -319,21 +329,28 @@ extern int flag_gnu_xref;
    In general, it is `reasonable' to assume that for many programs,
    and better code can be generated in that case.  */
 
-int flag_assume_nonnull_objects;
+int flag_assume_nonnull_objects = 1;
 
 /* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
    objects. */
+
 int flag_huge_objects;
 
 /* Nonzero if we want to conserve space in the .o files.  We do this
    by putting uninitialized data and runtime initialized data into
    .common instead of .data at the expense of not flaging multiple
    definitions.  */
+
 int flag_conserve_space;
 
 /* Nonzero if we want to obey access control semantics.  */
+
 int flag_access_control = 1;
 
+/* Nonzero if we want to understand the operator names, i.e. 'bitand'.  */
+
+int flag_operator_names;
+
 /* Table of language-dependent -f options.
    STRING is the option name.  VARIABLE is the address of the variable.
    ON_VALUE is the value to store in VARIABLE
@@ -355,7 +372,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"labels-ok", &flag_labels_ok, 1},
   {"stats", &flag_detailed_statistics, 1},
   {"this-is-variable", &flag_this_is_variable, 1},
-  {"strict-prototype", &strict_prototypes_lang_cplusplus, 1},
+  {"strict-prototype", &flag_strict_prototype, 1},
   {"all-virtual", &flag_all_virtual, 1},
   {"memoize-lookups", &flag_memoize_lookups, 1},
   {"elide-constructors", &flag_elide_constructors, 1},
@@ -376,7 +393,9 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"vtable-thunks", &flag_vtable_thunks, 1},
   {"short-temps", &flag_short_temps, 1},
   {"access-control", &flag_access_control, 1},
-  {"nonansi-builtins", &flag_no_nonansi_builtin, 0}
+  {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
+  {"gnu-keywords", &flag_no_gnu_keywords, 0},
+  {"operator-names", &flag_operator_names, 1}
 };
 
 /* Decode the string P as a language-specific option.
@@ -552,6 +571,7 @@ lang_decode_option (p)
          warn_ctor_dtor_privacy = setting;
          warn_switch = setting;
          warn_format = setting;
+         warn_parentheses = setting;
          warn_missing_braces = setting;
          warn_extern_inline = setting;
          warn_nonvdtor = setting;
@@ -569,8 +589,8 @@ lang_decode_option (p)
       else return 0;
     }
   else if (!strcmp (p, "-ansi"))
-    flag_no_asm = 1, dollars_in_ident = 0, flag_no_nonansi_builtin = 1,
-    flag_ansi = 1;
+    dollars_in_ident = 0, flag_no_nonansi_builtin = 1, flag_ansi = 1,
+    flag_no_gnu_keywords = 1, flag_operator_names = 1;
 #ifdef SPEW_DEBUG
   /* Undocumented, only ever used when you're invoking cc1plus by hand, since
      it's probably safe to assume no sane person would ever want to use this
@@ -2674,10 +2694,10 @@ finish_file ()
      we'll need here.  */
   push_lang_context (lang_name_c);
 
-  /* Set up the name of the file-level functions we may need.  */
-  /* Use a global object (which is already required to be unique over
-     the program) rather than the file name (which imposes extra
-     constraints).  -- Raeburn@MIT.EDU, 10 Jan 1990.  */
+  if (static_ctors || vars || have_exception_handlers)
+    needs_messing_up = 1;
+  if (static_dtors)
+    needs_cleaning = 1;
 
   /* See if we really need the hassle.  */
   while (vars && needs_cleaning == 0)
@@ -2740,6 +2760,10 @@ finish_file ()
       vars = TREE_CHAIN (vars);
     }
 
+  for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors))
+    expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors),
+                                          NULL_TREE));
+      
   expand_end_bindings (getdecls(), 1, 0);
   poplevel (1, 0, 0);
   pop_momentary ();
@@ -2753,7 +2777,7 @@ finish_file ()
  mess_up:
   /* Must do this while we think we are at the top level.  */
   vars = nreverse (static_aggregates);
-  if (vars != NULL_TREE || have_exception_handlers)
+  if (needs_messing_up)
     {
       fnname = get_file_function_name ('I');
       start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0);
@@ -2797,6 +2821,7 @@ finish_file ()
                 the same acess rights as a member function.  */
              DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
 
+#if 0
              if (init)
                {
                  if (TREE_CODE (init) == VAR_DECL)
@@ -2815,7 +2840,6 @@ finish_file ()
                              && CONSTRUCTOR_ELTS (init) == NULL_TREE)
                            init = NULL_TREE;
                        }
-#if 0
                      else if (TREE_TYPE (decl) == TREE_TYPE (init))
                        {
 #if 1
@@ -2828,9 +2852,9 @@ finish_file ()
                          init = DECL_INITIAL (init);
 #endif                         /* 1 */
                        }
-#endif                         /* 0 */
                    }
                }
+#endif                         /* 0 */
              if (IS_AGGR_TYPE (TREE_TYPE (decl))
                  || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
                expand_aggr_init (decl, init, 0, 0);
@@ -2865,6 +2889,10 @@ finish_file ()
          expand_cleanups_to (old_cleanups);
        }
 
+      for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
+       expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors),
+                                              NULL_TREE));
+      
       expand_end_bindings (getdecls(), 1, 0);
       poplevel (1, 0, 0);
       pop_momentary ();
index 87ec7a8..1490f6f 100644 (file)
@@ -43,7 +43,12 @@ tree builtin_return_address_fndecl;
 #define TRY_NEW_EH
 #endif
 #endif
-#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips)
+#ifdef _IBMR2
+#ifndef __rs6000
+#define __rs6000
+#endif
+#endif
+#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips) || defined (__arm)
 #define TRY_NEW_EH
 #endif
 #endif
@@ -123,6 +128,16 @@ expand_throw (exp)
 
 #else
 
+/* Make 'label' the first numbered label of the current function */
+void
+make_first_label(label)
+     rtx label;
+{
+  if (CODE_LABEL_NUMBER(label) < get_first_label_num())
+    set_new_first_and_last_label_num (CODE_LABEL_NUMBER(label),
+                                     max_label_num());
+}
+
 static int
 doing_eh (do_warn)
      int do_warn;
@@ -236,9 +251,16 @@ void
 exception_section ()
 {
 #ifdef ASM_OUTPUT_SECTION_NAME
-  named_section (".gcc_except_table");
+  named_section (NULL_TREE, ".gcc_except_table");
+#else
+  if (flag_pic)
+    data_section ();
+  else
+#if defined(__rs6000)
+    data_section ();
 #else
-  text_section ();
+    readonly_data_section ();
+#endif
 #endif
 }
 
@@ -576,6 +598,10 @@ push_eh_entry (stack)
   entry->exception_handler_label = gen_label_rtx ();
   pop_rtl_from_perm ();
 
+  LABEL_PRESERVE_P (entry->start_label) = 1;
+  LABEL_PRESERVE_P (entry->end_label) = 1;
+  LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
+
   entry->finalization = NULL_TREE;
 
   node->entry = entry;
@@ -794,9 +820,9 @@ init_exception_processing ()
   saved_throw_value = gen_rtx (REG, Pmode, 5);
 #endif
 #ifdef __rs6000
-  saved_pc = gen_rtx (REG, Pmode, 12);
-  saved_throw_type = gen_rtx (REG, Pmode, 13);
-  saved_throw_value = gen_rtx (REG, Pmode, 14);
+  saved_pc = gen_rtx (REG, Pmode, 13);
+  saved_throw_type = gen_rtx (REG, Pmode, 14);
+  saved_throw_value = gen_rtx (REG, Pmode, 15);
 #endif
 #ifdef __hppa
   saved_pc = gen_rtx (REG, Pmode, 5);
@@ -813,6 +839,11 @@ init_exception_processing ()
   saved_throw_type = gen_rtx (REG, Pmode, 17);
   saved_throw_value = gen_rtx (REG, Pmode, 18);
 #endif
+#ifdef __arm
+  saved_pc = gen_rtx (REG, Pmode, 7);
+  saved_throw_type = gen_rtx (REG, Pmode, 8);
+  saved_throw_value = gen_rtx (REG, Pmode, 9);
+#endif
   new_eh_queue (&ehqueue);
   new_eh_queue (&eh_table_output_queue);
   new_eh_stack (&ehstack);
@@ -958,7 +989,13 @@ expand_start_all_catch ()
   entry->end_label = gen_label_rtx ();
   entry->exception_handler_label = gen_label_rtx ();
   entry->finalization = TerminateFunctionCall;
+  assemble_external (TREE_OPERAND (Terminate, 0));
   pop_rtl_from_perm ();
+
+  LABEL_PRESERVE_P (entry->start_label) = 1;
+  LABEL_PRESERVE_P (entry->end_label) = 1;
+  LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
+
   emit_label (entry->end_label);
 
   enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
@@ -969,6 +1006,7 @@ expand_start_all_catch ()
   /* Will this help us not stomp on it? */
   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
+  make_first_label(throw_label);
   emit_jump (throw_label);
   emit_label (entry->exception_handler_label);
   expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
@@ -992,6 +1030,7 @@ expand_end_all_catch ()
   emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
                                     Pmode,
                                     top_label_entry (&caught_return_label_stack)));
+  make_first_label(throw_label);
   emit_jump (throw_label);
 
   /* Find the start of the catch block.  */
@@ -1052,7 +1091,13 @@ expand_leftover_cleanups ()
       entry.end_label = label;
       entry.exception_handler_label = gen_label_rtx ();
       entry.finalization = TerminateFunctionCall;
+      assemble_external (TREE_OPERAND (Terminate, 0));
       pop_rtl_from_perm ();
+
+      LABEL_PRESERVE_P (entry.start_label) = 1;
+      LABEL_PRESERVE_P (entry.end_label) = 1;
+      LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
+
       emit_label (label);
 
       enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
@@ -1063,6 +1108,7 @@ expand_leftover_cleanups ()
       /* Will this help us not stomp on it? */
       emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
       emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
+      make_first_label(throw_label);
       emit_jump (throw_label);
       emit_label (entry.exception_handler_label);
       expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
@@ -1143,6 +1189,7 @@ expand_start_catch_block (declspecs, declarator)
                                    NULL_TREE));
       catch_match_fcall = build_function_call (CatchMatch, params);
       call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
+      assemble_external (TREE_OPERAND (CatchMatch, 0));
 
       return_value_rtx =
        hard_function_value (integer_type_node, catch_match_fcall);
@@ -1192,6 +1239,7 @@ void expand_end_catch_block ()
       emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
                                         Pmode,
                                         top_label_entry (&caught_return_label_stack)));
+      make_first_label(throw_label);
       emit_jump (throw_label);
       /* No associated finalization.  */
       entry.finalization = NULL_TREE;
@@ -1210,6 +1258,10 @@ void expand_end_catch_block ()
       entry.start_label = start_protect_label_rtx;
       entry.end_label = end_protect_label_rtx;
 
+      LABEL_PRESERVE_P (entry.start_label) = 1;
+      LABEL_PRESERVE_P (entry.end_label) = 1;
+      LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
+
       /* These set up a call to throw the caught exception into the outer
        context.  */
       enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
@@ -1279,6 +1331,7 @@ do_unwind (throw_label)
                                            gen_rtx (LABEL_REF, Pmode, throw_label)), NULL_TREE);
   
   do_function_call (Unwind, params, NULL_TREE);
+  assemble_external (TREE_OPERAND (Unwind, 0));
   emit_barrier ();
 #endif
 #if m88k
@@ -1304,9 +1357,18 @@ do_unwind (throw_label)
                                                     (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
 #endif
 #endif
+#ifdef __arm
+  if (flag_omit_frame_pointer)
+    sorry ("this implementation of exception handling requires a frame pointer");
+
+  emit_move_insn (stack_pointer_rtx,
+                 gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -8)));
+  emit_move_insn (hard_frame_pointer_rtx,
+                 gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -12)));
+#endif
 }
 
-/* is called from expand_excpetion_blocks () to generate the code in a function
+/* is called from expand_exception_blocks () to generate the code in a function
    to "throw" if anything in the function needs to preform a throw.
 
    expands "throw" as the following psuedo code:
@@ -1333,12 +1395,14 @@ expand_builtin_throw ()
   rtx unwind_and_throw = gen_label_rtx ();
   rtx goto_unwind_and_throw = gen_label_rtx ();
 
+  make_first_label(throw_label);
   emit_label (throw_label);
 
   /* search for an exception handler for the saved_pc */
   return_val_rtx = do_function_call (FirstExceptionMatch,
                                     tree_cons (NULL_TREE, make_tree (ptr_type_node, saved_pc), NULL_TREE),
                                     ptr_type_node);
+  assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
 
   /* did we find one? */
   emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
@@ -1354,9 +1418,15 @@ expand_builtin_throw ()
   emit_label (gotta_rethrow_it);
 
   /* call to  __builtin_return_address () */
+#ifdef __arm
+/* This replaces a 'call' to __builtin_return_address */
+  return_val_rtx = gen_reg_rtx (Pmode);
+  emit_move_insn (return_val_rtx, gen_rtx (MEM, SImode, plus_constant (hard_frame_pointer_rtx, -4)));
+#else
   params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
   fcall = build_function_call (BuiltinReturnAddress, params);
   return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
+#endif
 
   /* did __builtin_return_address () return a valid address? */
   emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
@@ -1364,20 +1434,35 @@ expand_builtin_throw ()
 
   emit_jump_insn (gen_beq (gotta_call_terminate));
 
+#ifdef __arm
+  /* On the ARM, '__builtin_return_address',  must have 4
+     subtracted from it. */
+  emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-4)));
+
+  /* If we are generating code for an ARM2/ARM3 machine or for an ARM6 in 26 bit
+     mode, the condition codes must be masked out of the return value, or else
+     they will confuse BuiltinReturnAddress.  This does not apply to ARM6 and
+     later processors when running in 32 bit mode. */
+  if (!TARGET_6)
+    emit_insn (gen_rtx (SET, SImode, return_val_rtx, gen_rtx (AND, SImode, return_val_rtx, GEN_INT (0x03fffffc))));
+#else
 #ifndef sparc
   /* On the SPARC, __builtin_return_address is already -8, no need to
      subtract any more from it. */
   emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1)));
 #endif
+#endif
 
   /* yes it did */
   emit_move_insn (saved_pc, return_val_rtx);
   do_unwind (throw_label);
+  make_first_label(throw_label);
   emit_jump (throw_label);
 
   /* no it didn't --> therefore we need to call terminate */
   emit_label (gotta_call_terminate);
   do_function_call (Terminate, NULL_TREE, NULL_TREE);
+  assemble_external (TREE_OPERAND (Terminate, 0));
 }
 
 
@@ -1424,7 +1509,7 @@ expand_exception_blocks ()
 
        1. Allocate space to save the current PC onto the stack.
        2. Generate and emit a label and save its address into the
-               newly allocate stack space since we can't save the pc directly.
+               newly allocated stack space since we can't save the pc directly.
        3. If this is the first call to throw in this function:
                generate a label for the throw block
        4. jump to the throw block label.  */
@@ -1476,6 +1561,7 @@ expand_throw (exp)
       /* This part is easy, as we dont' have to do anything else.  */
     }
 
+  make_first_label(throw_label);
   emit_jump (throw_label);
 }
 
index 2ed6f80..1e37d3f 100644 (file)
@@ -19,8 +19,10 @@ __headof__, HEADOF, NORID
 __inline, SCSPEC, RID_INLINE
 __inline__, SCSPEC, RID_INLINE
 __label__, LABEL, NORID
+__signature__, AGGR, RID_SIGNATURE     /* Extension */,
 __signed, TYPESPEC, RID_SIGNED
 __signed__, TYPESPEC, RID_SIGNED
+__sigof__, SIGOF, NORID                /* Extension */,
 __typeof, TYPEOF, NORID
 __typeof__, TYPEOF, NORID
 __volatile, TYPE_QUAL, RID_VOLATILE
index cbff4c7..8a73e7c 100644 (file)
@@ -2376,9 +2376,9 @@ add_friend (type, decl)
            {
              if (decl == TREE_VALUE (friends))
                {
-                 cp_pedwarn ("`%D' is already a friend of class `%T'",
+                 cp_warning ("`%D' is already a friend of class `%T'",
                              decl, type);
-                 cp_pedwarn_at ("previous friend declaration of `%D'",
+                 cp_warning_at ("previous friend declaration of `%D'",
                                 TREE_VALUE (friends));
                  return;
                }
@@ -2948,12 +2948,15 @@ build_new (placement, decl, init, use_global_new)
   else
     size = size_in_bytes (type);
 
+  if (true_type == void_type_node)
+    {
+      error ("invalid type for new: `void'");
+      return error_mark_node;
+    }
+
   if (TYPE_SIZE (true_type) == 0)
     {
-      if (true_type == void_type_node)
-       error ("invalid type for new: `void'");
-      else
-       incomplete_type_error (0, true_type);
+      incomplete_type_error (0, true_type);
       return error_mark_node;
     }
 
index 97f1f02..09424b0 100644 (file)
@@ -403,6 +403,8 @@ void
 init_lex ()
 {
   extern char *(*decl_printable_name) ();
+  extern int flag_no_gnu_keywords;
+  extern int flag_operator_names;
 
   int i;
 
@@ -788,23 +790,21 @@ init_lex ()
     }
 #endif
 
-  if (! (flag_gc || flag_rtti))
+  if (! (flag_gc || flag_rtti) || flag_no_gnu_keywords)
     {
       UNSET_RESERVED_WORD ("classof");
       UNSET_RESERVED_WORD ("headof");
     }
-  if (! flag_handle_signatures)
+  if (! flag_handle_signatures || flag_no_gnu_keywords)
     {
       /* Easiest way to not recognize signature
         handling extensions...  */
       UNSET_RESERVED_WORD ("signature");
       UNSET_RESERVED_WORD ("sigof");
     }
-  if (flag_no_asm)
-    UNSET_RESERVED_WORD ("asm");
-  if (flag_no_asm || flag_traditional)
+  if (flag_no_asm || flag_no_gnu_keywords)
     UNSET_RESERVED_WORD ("typeof");
-  if (!flag_ansi)
+  if (! flag_operator_names)
     {
       /* These are new ANSI keywords that may break code.  */
       UNSET_RESERVED_WORD ("and");
@@ -815,6 +815,8 @@ init_lex ()
       UNSET_RESERVED_WORD ("or");
       UNSET_RESERVED_WORD ("xor");
     }
+  if (! flag_traditional)
+    UNSET_RESERVED_WORD ("overload");
 
   token_count = init_parse ();
   interface_unknown = 1;
@@ -4211,7 +4213,7 @@ real_yylex ()
                  goto tryagain;
                if (width < HOST_BITS_PER_INT
                    && (unsigned) c >= (1 << width))
-                 pedwarn ("escape sequence out of range for character");
+                 warning ("escape sequence out of range for character");
 #ifdef MAP_CHARACTER
                if (isprint (c))
                  c = MAP_CHARACTER (c);
@@ -4328,7 +4330,7 @@ real_yylex ()
                if (!wide_flag
                    && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
                    && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
-                 pedwarn ("escape sequence out of range for character");
+                 warning ("escape sequence out of range for character");
              }
            else if (c == '\n')
              {
@@ -4483,7 +4485,7 @@ real_yylex ()
            }
        else if ((c == '-') && (c1 == '>'))
          {
-           nextchar = skip_white_space (getch ());
+           nextchar = getch ();
            if (nextchar == '*')
              {
                nextchar = -1;
@@ -4510,11 +4512,22 @@ real_yylex ()
                value = MIN_MAX;
                nextchar = c1;
              }
-           if (flag_ansi)
+           if (pedantic)
              pedwarn ("use of `operator %s' is not standard C++",
                       token_buffer);
            goto done;
          }
+       /* digraphs */
+       else if (c == '<' && c1 == '%')
+         { value = '{'; goto done; }
+       else if (c == '<' && c1 == ':')
+         { value = '['; goto done; }
+       else if (c == '%' && c1 == '>')
+         { value = '}'; goto done; }
+       else if (c == '%' && c1 == ':')
+         { value = '#'; goto done; }
+       else if (c == ':' && c1 == '>')
+         { value = ']'; goto done; }
 
        nextchar = c1;
        token_buffer[1] = 0;
index 105ca3a..816aacd 100644 (file)
@@ -123,6 +123,7 @@ extern int looking_for_template;
 
 /* Tell the lexer where to look for names.  */
 extern tree got_scope;
+extern tree got_object;
 
 /* Pending language change.
    Positive is push count, negative is pop count.  */
index 345e31b..882c2fd 100644 (file)
@@ -1246,7 +1246,8 @@ expr_no_commas:
        | expr_no_commas '?' xexpr ':' expr_no_commas
                { $$ = build_x_conditional_expr ($$, $3, $5); }
        | expr_no_commas '=' expr_no_commas
-               { $$ = build_modify_expr ($$, NOP_EXPR, $3); }
+               { $$ = build_modify_expr ($$, NOP_EXPR, $3);
+                  C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
        | expr_no_commas ASSIGN expr_no_commas
                { register tree rval;
                  if ((rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, $$, $3,
@@ -1333,7 +1334,12 @@ primary:
        | string
                { $$ = combine_strings ($$); }
        | '(' expr ')'
-               { $$ = $2; }
+               { char class = TREE_CODE_CLASS (TREE_CODE ($2));
+                 if (class == 'e' || class == '1'
+                     || class == '2' || class == '<')
+                    /* This inhibits warnings in truthvalue_conversion. */
+                   C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK);
+                 $$ = $2; }
        | '(' error ')'
                { $$ = error_mark_node; }
        | '('
@@ -1538,11 +1544,14 @@ primary:
        | overqualified_id LEFT_RIGHT
                { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
        | object unqualified_id  %prec UNARY
-               { $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
+               { got_object = NULL_TREE;
+                 $$ = build_component_ref ($$, $2, NULL_TREE, 1); }
        | object qualified_id %prec UNARY
-               { $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
+               { got_object = NULL_TREE;
+                 $$ = build_object_ref ($$, OP0 ($2), OP1 ($2)); }
        | object unqualified_id '(' nonnull_exprlist ')'
                {
+                 got_object = NULL_TREE;
 #if 0
                  /* This is a future direction of this code, but because
                     build_x_function_call cannot always undo what is done
@@ -1558,6 +1567,7 @@ primary:
                }
        | object unqualified_id LEFT_RIGHT
                {
+                 got_object = NULL_TREE;
 #if 0
                  /* This is a future direction of this code, but because
                     build_x_function_call cannot always undo what is done
@@ -1573,6 +1583,7 @@ primary:
                }
        | object qualified_id '(' nonnull_exprlist ')'
                {
+                 got_object = NULL_TREE;
                  if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
                    {
                      warning ("signature name in scope resolution ignored");
@@ -1584,6 +1595,7 @@ primary:
                }
        | object qualified_id LEFT_RIGHT
                {
+                 got_object = NULL_TREE;
                  if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
                    {
                      warning ("signature name in scope resolution ignored");
@@ -1595,14 +1607,16 @@ primary:
                }
        /* p->int::~int() is valid -- 12.4 */
        | object '~' TYPESPEC LEFT_RIGHT
-               { 
+               {
+                 got_object = NULL_TREE;
                  if (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);
                }
        | object TYPESPEC SCOPE '~' TYPESPEC LEFT_RIGHT
-               { 
+               {
+                 got_object = NULL_TREE;
                  if ($2 != $5)
                    cp_error ("destructor specifier `%T::~%T()' must have matching names", $2, $5);
                  if (TREE_CODE (TREE_TYPE ($1))
@@ -1610,6 +1624,11 @@ primary:
                    cp_error ("`%E' is not of type `%T'", $1, $2);
                  $$ = convert (void_type_node, $1);
                }
+       | object error
+               {
+                 got_object = NULL_TREE;
+                 $$ = error_mark_node;
+               }
        ;
 
 /* Not needed for now.
@@ -1690,9 +1709,11 @@ nodecls:
        ;
 
 object:          primary '.'
+               { got_object = TREE_TYPE ($$); }
        | primary POINTSAT
                {
-                 $$ = build_x_arrow ($$);
+                 $$ = build_x_arrow ($$); 
+                 got_object = TREE_TYPE ($$);
                }
        ;
 
@@ -3288,7 +3309,7 @@ simple_stmt:
                      else if (success == 2)
                        {
                          cp_error ("duplicate case value `%E'", $2);
-                         cp_error_at ("`%E' previously used here", duplicate);
+                         cp_error_at ("previously used here", duplicate);
                        }
                      else if (success == 3)
                        warning ("case value out of range");
index e10acbe..a9dfb84 100644 (file)
@@ -1257,6 +1257,8 @@ tsubst (t, args, nargs, in_decl)
                type = newtype;
 
                fnargs = copy_node (DECL_ARGUMENTS (t));
+               TREE_CHAIN (fnargs) = TREE_CHAIN (DECL_ARGUMENTS (t));
+
                /* In this case we need "in-charge" flag saying whether
                   this constructor is responsible for initialization
                   of virtual baseclasses or not.  */
@@ -1419,7 +1421,7 @@ tsubst (t, args, nargs, in_decl)
                  r = build_lang_decl (FUNCTION_DECL, r, type);
                  DECL_ASSEMBLER_NAME (r) = a;
                }
-             else if (DECL_INLINE (r) && DECL_SAVED_INSNS (r))
+             else if (TREE_STATIC (r))
                {
                  /* This overrides the template version, use it. */
                  return r;
@@ -1718,7 +1720,7 @@ instantiate_template (tmpl, targ_ptr)
 
   /* If we have a preexisting version of this function, don't expand
      the template version, use the other instead.  */
-  if (DECL_INLINE (fndecl) && DECL_SAVED_INSNS (fndecl))
+  if (TREE_STATIC (fndecl))
     {
       SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
       p = (struct pending_inline *)0;
@@ -2448,7 +2450,7 @@ do_function_instantiation (declspecs, declarator, storage)
          {
            int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
            tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
-           int i, dummy;
+           int i, dummy = 0;
            i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
                                  TYPE_ARG_TYPES (TREE_TYPE (fn)),
                                  TYPE_ARG_TYPES (TREE_TYPE (decl)),
@@ -2460,6 +2462,7 @@ do_function_instantiation (declspecs, declarator, storage)
                else
                  result = instantiate_template (fn, targs);
              }
+           free (targs);
          }
     }
   if (! result)
index 9fb8e63..1c0e712 100644 (file)
@@ -1089,18 +1089,29 @@ lookup_field (xbasetype, name, protect, want_type)
     entry = 0;
 
   rval = lookup_field_1 (type, name);
-  if (rval || lookup_fnfields_here (type, name)>=0)
-    {
-      rval_binfo = basetype_path;
-      rval_binfo_h = rval_binfo;
-    }
-
-  if (rval && TREE_CODE (rval) != TYPE_DECL && want_type)
-    rval = NULL_TREE;
 
-  if (rval)
+  if (rval || lookup_fnfields_here (type, name) >= 0)
     {
-      if (protect)
+      if (rval)
+       {
+         if (want_type)
+           {
+             if (TREE_CODE (rval) != TYPE_DECL)
+               {
+                 rval = purpose_member (name, CLASSTYPE_TAGS (type));
+                 if (rval)
+                   rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
+               }
+           }
+         else
+           {
+             if (TREE_CODE (rval) == TYPE_DECL
+                 && lookup_fnfields_here (type, name) >= 0)
+               rval = NULL_TREE;
+           }
+       }
+
+      if (protect && rval)
        {
          if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval))
            this_v = compute_access (basetype_path, rval);
@@ -1259,12 +1270,33 @@ lookup_field (xbasetype, name, protect, want_type)
     if (entry)
       TREE_VALUE (entry) = rval;
 
-    if (want_type && (rval == NULL_TREE || TREE_CODE (rval) != TYPE_DECL))
+    if (rval_binfo)
       {
-       rval = NULL_TREE;
-       errstr = 0;
+       type = BINFO_TYPE (rval_binfo);
+
+       if (rval)
+         {
+           if (want_type)
+             {
+               if (TREE_CODE (rval) != TYPE_DECL)
+                 {
+                   rval = purpose_member (name, CLASSTYPE_TAGS (type));
+                   if (rval)
+                     rval = TYPE_MAIN_DECL (TREE_VALUE (rval));
+                 }
+             }
+           else
+             {
+               if (TREE_CODE (rval) == TYPE_DECL
+                   && lookup_fnfields_here (type, name) >= 0)
+                 rval = NULL_TREE;
+             }
+         }
       }
 
+    if (rval == NULL_TREE)
+      errstr = 0;
+
     /* If this FIELD_DECL defines its own access level, deal with that.  */
     if (rval && errstr == 0
        && ((protect&1) || entry)
@@ -1948,11 +1980,51 @@ get_matching_virtual (binfo, fndecl, dtorp)
                   == TYPE_READONLY (instptr_type))
                  && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3))
                {
-                 if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE
-                     && ! comptypes (TREE_TYPE (TREE_TYPE (tmp)), drettype, 1))
+                 tree brettype = TREE_TYPE (TREE_TYPE (tmp));
+                 if (comptypes (brettype, drettype, 1))
+                   /* OK */;
+                 else if
+                   (TREE_CODE (brettype) == TREE_CODE (drettype)
+                    && (TREE_CODE (brettype) == POINTER_TYPE
+                        || TREE_CODE (brettype) == REFERENCE_TYPE)
+                    && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (brettype)),
+                                  TYPE_MAIN_VARIANT (TREE_TYPE (drettype)),
+                                  0))
+                     /* covariant return type */
+                   {
+                     tree b = TREE_TYPE (brettype), d = TREE_TYPE (drettype);
+                     if (TYPE_MAIN_VARIANT (b) != TYPE_MAIN_VARIANT (d))
+                       {
+                         tree binfo = get_binfo (b, d, 1);
+                         if (binfo != error_mark_node
+                             && ! BINFO_OFFSET_ZEROP (binfo))
+                           sorry ("adjusting pointers for covariant returns");
+                       }
+                     if (TYPE_READONLY (d) > TYPE_READONLY (b))
+                       {
+                         cp_error ("return type of `%#D' adds const", fndecl);
+                         cp_error_at ("  overriding definition as `%#D'",
+                                      tmp);
+                       }
+                     else if (TYPE_VOLATILE (d) > TYPE_VOLATILE (b))
+                       {
+                         cp_error ("return type of `%#D' adds volatile",
+                                   fndecl);
+                         cp_error_at ("  overriding definition as `%#D'",
+                                      tmp);
+                       }
+                   }
+                 else if (IS_AGGR_TYPE_2 (brettype, drettype)
+                          && comptypes (brettype, drettype, 0))
+                   {
+                     error ("invalid covariant return type (must use pointer or reference)");
+                     cp_error_at ("  overriding `%#D'", tmp);
+                     cp_error ("  with `%#D'", fndecl);
+                   }
+                 else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE)
                    {
                      cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
-                     cp_error_at ("overriding definition as `%#D'", tmp);
+                     cp_error_at ("  overriding definition as `%#D'", tmp);
                      SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
                    }
                  break;
@@ -2192,7 +2264,7 @@ dfs_walk (binfo, fn, qfn)
     {
       tree base_binfo = TREE_VEC_ELT (binfos, i);
 
-      if ((*qfn)(base_binfo))
+      if (qfn == 0 || (*qfn)(base_binfo))
        {
          if (fn == dfs_init_vbase_pointers)
            {
@@ -2800,8 +2872,14 @@ dfs_pushdecls (binfo)
                    ? DECL_CLASS_CONTEXT (value)
                      : DECL_CONTEXT (value);
 
-                 if (context && (context == type
-                                 || TYPE_DERIVES_FROM (context, type)))
+                 if (context == type)
+                   {
+                     if (TREE_CODE (value) == TYPE_DECL
+                         && DECL_ARTIFICIAL (value))
+                       value = fields;
+                     /* else the old value wins */
+                   }
+                 else if (context && TYPE_DERIVES_FROM (context, type))
                    value = fields;
                  else
                    value = tree_cons (NULL_TREE, fields,
@@ -3210,3 +3288,24 @@ reinit_search_statistics ()
   n_outer_fields_searched = 0;
   n_contexts_saved = 0;
 }
+
+static tree conversions;
+static void
+add_conversions (binfo)
+     tree binfo;
+{
+  tree tmp = CLASSTYPE_FIRST_CONVERSION (BINFO_TYPE (binfo));
+  for (; tmp && IDENTIFIER_TYPENAME_P (DECL_NAME (tmp));
+       tmp = TREE_CHAIN (tmp))
+    conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
+                            conversions);
+}
+
+tree
+lookup_conversions (type)
+     tree type;
+{
+  conversions = NULL_TREE;
+  dfs_walk (TYPE_BINFO (type), add_conversions, 0);
+  return conversions;
+}
index c28e2c1..296c8f6 100644 (file)
@@ -242,6 +242,7 @@ int looking_for_template;
 
 extern struct obstack *current_obstack, *saveable_obstack;
 tree got_scope;
+tree got_object;
 
 int
 yylex()
@@ -316,7 +317,7 @@ yylex()
              if (lastiddecl != trrr)
                {
                  lastiddecl = trrr;
-                 if (got_scope)
+                 if (got_scope || got_object)
                    tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
                }
              break;
@@ -334,8 +335,11 @@ yylex()
        lastiddecl = trrr;
       got_scope = NULL_TREE;
       /* and fall through to... */
+    case IDENTIFIER_DEFN:
     case TYPENAME:
+    case TYPENAME_DEFN:
     case PTYPENAME:
+    case PTYPENAME_DEFN:
       consume_token ();
       if (looking_for_typename > 0)
        looking_for_typename--;
index 82583c7..bb652c7 100644 (file)
@@ -102,6 +102,11 @@ lvalue_p (ref)
 
     case COMPOUND_EXPR:
       return lvalue_p (TREE_OPERAND (ref, 1));
+
+    case MAX_EXPR:
+    case MIN_EXPR:
+      return (lvalue_p (TREE_OPERAND (ref, 0))
+             && lvalue_p (TREE_OPERAND (ref, 1)));
     }
 
   return 0;
@@ -570,9 +575,13 @@ layout_vbasetypes (rec, max)
       BINFO_OFFSET (vbase_types) = offset;
 
       if (TREE_CODE (TYPE_SIZE (basetype)) == INTEGER_CST)
-       const_size += MAX (BITS_PER_UNIT,
-                          TREE_INT_CST_LOW (TYPE_SIZE (basetype))
-                          - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
+       {
+         /* Every virtual baseclass takes a least a UNIT, so that we can
+            take it's address and get something different for each base.  */
+         const_size += MAX (BITS_PER_UNIT,
+                            TREE_INT_CST_LOW (TYPE_SIZE (basetype))
+                            - TREE_INT_CST_LOW (CLASSTYPE_VBASE_SIZE (basetype)));
+       }
       else if (var_size == 0)
        var_size = TYPE_SIZE (basetype);
       else
@@ -581,6 +590,15 @@ layout_vbasetypes (rec, max)
       vbase_types = TREE_CHAIN (vbase_types);
     }
 
+  if (const_size)
+    {
+      /* Because a virtual base might take a single byte above,
+        we have to re-adjust the total size to make sure it it
+        a multiple of the alignment.  */
+      /* Give the whole object the alignment it wants.  */
+      const_size = CEIL (const_size, record_align) * record_align;
+    }
+
   /* Set the alignment in the complete type.  We don't set CLASSTYPE_ALIGN
    here, as that is for this class, without any virtual base classes.  */
   TYPE_ALIGN (rec) = record_align;
index 60cb4f4..f226f28 100644 (file)
@@ -202,9 +202,6 @@ commonparms (p1, p2)
     {
       if (TREE_PURPOSE (p1) && !TREE_PURPOSE (p2))
        {
-         /* We used to give a warning here that advised about a default
-            argument being given in the prototype but not in the function's
-            declaration.  It's best not to bother.  */
          TREE_PURPOSE (n) = TREE_PURPOSE (p1);
          any_change = 1;
        }
@@ -352,6 +349,11 @@ common_type (t1, t2)
          return build_type_attribute_variant (t1, attributes);
        }
 
+      if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
+         || TYPE_MAIN_VARIANT (t2) == long_double_type_node)
+       return build_type_attribute_variant (long_double_type_node,
+                                            attributes);         
+
       /* Otherwise prefer the unsigned one.  */
 
       if (TREE_UNSIGNED (t1))
@@ -445,9 +447,12 @@ common_type (t1, t2)
       my_friendly_assert (TYPE_MAIN_VARIANT (t1) == t1
                          && TYPE_MAIN_VARIANT (t2) == t2, 306);
 
-      if (! binfo_or_else (t1, t2))
-         compiler_error ("common_type called with uncommon aggregate types");
-      return build_type_attribute_variant (t1, attributes);
+      if (DERIVED_FROM_P (t1, t2) && binfo_or_else (t1, t2))
+       return build_type_attribute_variant (t1, attributes);
+      else if (binfo_or_else (t2, t1))
+       return build_type_attribute_variant (t2, attributes);
+      else
+       compiler_error ("common_type called with uncommon aggregate types");
 
     case METHOD_TYPE:
       if (comptypes (TYPE_METHOD_BASETYPE (t1), TYPE_METHOD_BASETYPE (t2), 1)
@@ -761,9 +766,7 @@ comp_target_types (ttl, ttr, nptrs)
        case 1:
          return 1;
        case 2:
-         cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
-                     ttr, ttl);
-         return 1;
+         return -1;
        default:
          my_friendly_abort (112);
        }
@@ -780,17 +783,17 @@ comp_target_types (ttl, ttr, nptrs)
        return comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs);
       else if (comptypes (TYPE_OFFSET_BASETYPE (ttl), TYPE_OFFSET_BASETYPE (ttr), 0)
               && comp_target_types (TREE_TYPE (ttl), TREE_TYPE (ttr), nptrs))
-       {
-         cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
-                     ttr, ttl);
-         return 1;
-       }
+       return -1;
     }
   else if (IS_AGGR_TYPE (ttl))
     {
       if (nptrs < 0)
        return 0;
-      return comptypes (TYPE_POINTER_TO (ttl), TYPE_POINTER_TO (ttr), 0);
+      if (comptypes (TYPE_POINTER_TO (ttl), TYPE_POINTER_TO (ttr), 0))
+       return 1;
+      if (comptypes (TYPE_POINTER_TO (ttr), TYPE_POINTER_TO (ttl), 0))
+       return -1;
+      return 0;
     }
 
   return 0;
@@ -1223,7 +1226,7 @@ c_sizeof_nowarn (type)
 
   /* Convert in case a char is more than one unit.  */
   t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), 
-                    size_int (TYPE_PRECISION (char_type_node)));
+                 size_int (TYPE_PRECISION (char_type_node)));
   force_fit_type (t, 0);
   return t;
 }
@@ -1665,7 +1668,14 @@ build_component_ref (datum, component, basetype_path, protect)
                  return error_mark_node;
                }
              else
-               return build (COMPONENT_REF, unknown_type_node, datum, fndecls);
+               {
+                 /* Just act like build_offset_ref, since the object does
+                     not matter unless we're actually calling the function.  */
+                 tree t = build_tree_list (error_mark_node, fndecls);
+                 TREE_TYPE (t) = build_offset_type (basetype,
+                                                    unknown_type_node);
+                 return t;
+               }
            }
 
 #if 0
@@ -2187,12 +2197,13 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
   if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
     {
       tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
-      tree index = save_expr (convert (integer_type_node,
-                                      build_component_ref (function,
-                                                           index_identifier,
-                                                           0, 0)));
-      tree e1 = build (GT_EXPR, integer_type_node, index, integer_zero_node);
-      tree delta = build_component_ref (function, delta_identifier, 0, 0);
+      tree index = save_expr (build_component_ref (function,
+                                                  index_identifier,
+                                                  0, 0));
+      tree e1 = build (GT_EXPR, delta_type_node, index,
+                      convert (delta_type_node, integer_zero_node));
+      tree delta = convert (ptrdiff_type_node,
+                           build_component_ref (function, delta_identifier, 0, 0));
       tree delta2 = DELTA2_FROM_PTRMEMFUNC (function);
       tree e2;
       tree e3;
@@ -2208,11 +2219,11 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
       vtbl
        = build (PLUS_EXPR,
                 build_pointer_type (build_pointer_type (vtable_entry_type)),
-                vtbl, convert (sizetype, delta2));
+                vtbl, convert (ptrdiff_type_node, delta2));
       vtbl = build_indirect_ref (vtbl, NULL_PTR);
-      aref = build_array_ref (vtbl, size_binop (MINUS_EXPR,
-                                               index,
-                                               integer_one_node));
+      aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
+                                                    index,
+                                                    integer_one_node, 1));
       if (! flag_vtable_thunks)
        {
          aref = save_expr (aref);
@@ -2222,14 +2233,14 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
          if (/* !building_cleanup && */ TREE_CODE (aref) == INDIRECT_REF)
            TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
       
-         delta = build (PLUS_EXPR, integer_type_node,
-                        build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
-                        delta);
+         delta = build_binary_op (PLUS_EXPR,
+                                  build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
+                                  delta, 1);
        }
 
       *instance_ptrptr = build (PLUS_EXPR, TREE_TYPE (*instance_ptrptr),
                                *instance_ptrptr,
-                               convert (integer_type_node, delta));
+                               delta);
       if (flag_vtable_thunks)
        e2 = aref;
       else
@@ -3162,7 +3173,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
          tree delta21 = DELTA2_FROM_PTRMEMFUNC (op1);
          tree e1, e2, e3;
          tree integer_neg_one_node
-           = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+           = build_binary_op (MINUS_EXPR, integer_zero_node, integer_one_node, 1);
          e1 = build_binary_op (EQ_EXPR, index0, index1, 1);
          e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node, 1);
          e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, build_binary_op (EQ_EXPR, delta20, delta21, 1), 1);
@@ -3183,7 +3194,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
          tree delta21 = integer_zero_node;
          tree e1, e2, e3;
          tree integer_neg_one_node
-           = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+           = build_binary_op (MINUS_EXPR, integer_zero_node, integer_one_node, 1);
          if (TREE_CODE (TREE_OPERAND (op1, 0)) == FUNCTION_DECL
              && DECL_VINDEX (TREE_OPERAND (op1, 0)))
            {
@@ -3828,9 +3839,17 @@ build_unary_op (code, xarg, noconvert)
         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 (!noconvert)
@@ -3852,6 +3871,13 @@ build_unary_op (code, xarg, noconvert)
       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)
@@ -3873,6 +3899,13 @@ build_unary_op (code, xarg, noconvert)
       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)
@@ -3917,6 +3950,13 @@ 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);
@@ -4012,9 +4052,6 @@ build_unary_op (code, xarg, noconvert)
            }
          }
 
-       if (TREE_CODE (arg) == OFFSET_REF)
-         arg = resolve_offset_ref (arg);
-
        /* Complain about anything else that is not a true lvalue.  */
        if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
                                    || code == POSTINCREMENT_EXPR)
@@ -4244,7 +4281,9 @@ unary_complex_lvalue (code, arg)
   if (TREE_CODE (arg) == COND_EXPR)
     return rationalize_conditional_expr (code, arg);
 
-  if (TREE_CODE (arg) == MODIFY_EXPR)
+  if (TREE_CODE (arg) == MODIFY_EXPR
+      || TREE_CODE (arg) == PREINCREMENT_EXPR
+      || TREE_CODE (arg) == PREDECREMENT_EXPR)
     return unary_complex_lvalue
       (code, build (COMPOUND_EXPR, TREE_TYPE (TREE_OPERAND (arg, 0)),
                    arg, TREE_OPERAND (arg, 0)));
@@ -4499,7 +4538,7 @@ build_conditional_expr (ifexp, op1, op2)
       ifexp = op1 = save_expr (ifexp);
     }
 
-  ifexp = bool_truthvalue_conversion (default_conversion (ifexp));
+  ifexp = bool_truthvalue_conversion (ifexp);
 
   if (TREE_CODE (ifexp) == ERROR_MARK)
     return error_mark_node;
@@ -5780,8 +5819,7 @@ build_modify_expr (lhs, modifycode, rhs)
       int from_array;
       
       /* Allow array assignment in compiler-generated code.  */
-      if ((pedantic || flag_ansi)
-         && ! DECL_ARTIFICIAL (current_function_decl))
+      if (pedantic && ! DECL_ARTIFICIAL (current_function_decl))
        pedwarn ("ANSI C++ forbids assignment of arrays");
 
       /* Have to wrap this in RTL_EXPR for two cases:
@@ -6010,9 +6048,9 @@ get_delta_difference (from, to, force)
        {
          warning ("pointer to member conversion to virtual base class will only work if your very careful");
        }
-      return fold (size_binop (MINUS_EXPR,
-                              integer_zero_node,
-                              BINFO_OFFSET (binfo)));
+      return build_binary_op (MINUS_EXPR,
+                             integer_zero_node,
+                             BINFO_OFFSET (binfo), 1);
     }
   if (TREE_VIA_VIRTUAL (binfo))
     {
@@ -6069,14 +6107,14 @@ build_ptrmemfunc (type, pfn, force)
       if (TREE_CODE (pfn) != CONSTRUCTOR)
        {
          tree e1, e2, e3;
-         ndelta = convert (sizetype, build_component_ref (pfn, delta_identifier, 0, 0));
-         ndelta2 = convert (sizetype, DELTA2_FROM_PTRMEMFUNC (pfn));
+         ndelta = convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, 0, 0));
+         ndelta2 = convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
          index = build_component_ref (pfn, index_identifier, 0, 0);
          delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
                                        TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
                                        force);
-         delta = fold (size_binop (PLUS_EXPR, delta, ndelta));
-         delta2 = fold (size_binop (PLUS_EXPR, ndelta2, delta2));
+         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));
          
          u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
@@ -6136,7 +6174,7 @@ build_ptrmemfunc (type, pfn, force)
   delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
                                TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
                                force);
-  delta2 = fold (size_binop (PLUS_EXPR, delta2, delta));
+  delta2 = build_binary_op (PLUS_EXPR, delta2, delta, 1);
 
   if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
     warning ("assuming pointer to member function is non-virtual");
@@ -6159,7 +6197,7 @@ build_ptrmemfunc (type, pfn, force)
     }
   else
     {
-      index = fold (size_binop (MINUS_EXPR, integer_zero_node, integer_one_node));
+      index = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
 
       npfn = build1 (NOP_EXPR, type, pfn);
       TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
@@ -6306,6 +6344,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
     {
       register tree ttl = TREE_TYPE (type);
       register tree ttr;
+      int ctt = 0;
 
       if (coder == RECORD_TYPE)
        {
@@ -6358,7 +6397,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
         Meanwhile, the lhs target must have all the qualifiers of the rhs.  */
       else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
               || TYPE_MAIN_VARIANT (ttr) == void_type_node
-              || comp_target_types (type, rhstype, 1)
+              || (ctt = comp_target_types (type, rhstype, 1))
               || (unsigned_type (TYPE_MAIN_VARIANT (ttl))
                   == unsigned_type (TYPE_MAIN_VARIANT (ttr))))
        {
@@ -6366,17 +6405,21 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
          if (TYPE_MAIN_VARIANT (ttl) == void_type_node
              && TREE_CODE (ttr) == OFFSET_TYPE)
            {
-             error ("no standard conversion from pointer to member to `void *'");
+             cp_error ("no standard conversion from `%T' to `void *'", ttr);
              return error_mark_node;
            }
 
+         if (ctt < 0)
+           cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
+                       ttr, ttl);
+
          if (TYPE_MAIN_VARIANT (ttl) != void_type_node
              && TYPE_MAIN_VARIANT (ttr) == void_type_node
              && rhs != null_pointer_node)
            {
              if (coder == RECORD_TYPE)
-               pedwarn ("implicit conversion of signature pointer to type `%s'",
-                        type_as_string (type, 0));
+               cp_pedwarn ("implicit conversion of signature pointer to type `%T'",
+                           type);
              else
                pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s",
                         errtype);
@@ -6481,7 +6524,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
                ttl = unsigned_type (ttl);
            }
 
-         if (comp_target_types (ttl, ttr, nptrs))
+         if (comp_target_types (ttl, ttr, nptrs) > 0)
            {
              if (add_quals)
                {
@@ -6585,7 +6628,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
        }
       return null_pointer_node;
     }
-  else if ((codel == INTEGER_TYPE || codel == BOOLEAN_TYPE)
+  else if (codel == INTEGER_TYPE
           && (coder == POINTER_TYPE
               || (coder == RECORD_TYPE
                   && (IS_SIGNATURE_POINTER (rhstype)
@@ -6600,6 +6643,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
                    errtype, type, rhstype);
       return convert (type, rhs);
     }
+  else if (codel == BOOLEAN_TYPE
+          && (coder == POINTER_TYPE
+              || (coder == RECORD_TYPE
+                  && (IS_SIGNATURE_POINTER (rhstype)
+                      || TYPE_PTRMEMFUNC_FLAG (rhstype)
+                      || IS_SIGNATURE_REFERENCE (rhstype)))))
+    return convert (type, rhs);
 
   /* C++ */
   else if (((coder == POINTER_TYPE && TREE_CODE (rhs) == ADDR_EXPR