re PR c++/11667 (wider-than-int enums never compare equal to 0)
authorMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 29 Jul 2003 01:14:24 +0000 (01:14 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 29 Jul 2003 01:14:24 +0000 (01:14 +0000)
PR c++/11667
* c-common.c (shorten_compare): Take into account differences
between C and C++ representation for enumeration types.
* tree.h (set_min_and_max_values_for_integral_type): Declare.
* stor-layout.c (set_min_and_max_values_for_integral_type): New
function, broken out from ...
(fixup_signed_type): ... here and ...
(fixup_unsigned_type): ... here.

PR c++/11667
* call.c (standard_conversion): Allow all integral->enumeral
conversions, after marking them as bad.
* decl.c (finish_enum): Make sure that all enumerators are
properly converted to the underlying type.
(build_enumerator): Set DECL_CONTEXT for namespace-scope
enumeration types.
* pt.c (tsubst_copy): Adjust handling of CONST_DECLs accordingly.
(tsubst_enum): Tidy.

* Make-lang.in (typeck.o): Depend on convert.h.
(class.o): Likewise.
(rtti.o): Likewise.
* call.c: Include convert.h.
(convert_arg_to_ellipsis): Use convert_to_real.
* class.c: Include convert.h.
(build_base_path): Use convert_to_integer.
* rtti.c: Include convert.h.
(build_headof): Use convert_to_integer.
* typeck.c: Include convert.h.
(decay_conversion): Use convert_to_integer.
(build_unary_op): Use build_nop.
(get_delta_difference): Use convert_to_integer.
(build_ptrmemfunc): Avoid unncessary conversions.

From-SVN: r69909

15 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/decl.c
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/typeck.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/enum2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/overload1.C
gcc/tree.h

index c3e8f266a92b0e056daa48c5a8bca09b3e1d5794..c3059e557af1c74d1204ed7a9b78698791fca10c 100644 (file)
@@ -1,3 +1,14 @@
+2003-07-28  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11667
+       * c-common.c (shorten_compare): Take into account differences
+       between C and C++ representation for enumeration types.
+       * tree.h (set_min_and_max_values_for_integral_type): Declare.
+       * stor-layout.c (set_min_and_max_values_for_integral_type): New
+       function, broken out from ...
+       (fixup_signed_type): ... here and ...
+       (fixup_unsigned_type): ... here.
+
 2003-07-28  Zack Weinberg  <zack@codesourcery.com>
 
        * c-decl.c: Update commentary, adjust blank lines throughout.
index c579b16f37c3377470f62e7cbb81ec68f89573dc..8dea43bb028a0cc3bf81381c31bc95b04fbba270 100644 (file)
@@ -2214,10 +2214,12 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       type = c_common_signed_or_unsigned_type (unsignedp0,
                                               TREE_TYPE (primop0));
 
-      /* If TYPE is an enumeration, then we need to get its min/max
-        values from it's underlying integral type, not the enumerated
-        type itself.  */
-      if (TREE_CODE (type) == ENUMERAL_TYPE)
+      /* In C, if TYPE is an enumeration, then we need to get its
+        min/max values from it's underlying integral type, not the
+        enumerated type itself.  In C++, TYPE_MAX_VALUE and
+        TYPE_MIN_VALUE have already been set correctly on the
+        enumeration type.  */
+      if (!c_dialect_cxx() && TREE_CODE (type) == ENUMERAL_TYPE)
        type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0);
 
       maxval = TYPE_MAX_VALUE (type);
index abbe9ccbbc3245d1be3870f8c8550329e85846f7..64068a2cab5ae210f242e579a0c7ff608d7c678f 100644 (file)
@@ -1,3 +1,30 @@
+2003-07-28  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11667
+       * call.c (standard_conversion): Allow all integral->enumeral
+       conversions, after marking them as bad.
+       * decl.c (finish_enum): Make sure that all enumerators are
+       properly converted to the underlying type.
+       (build_enumerator): Set DECL_CONTEXT for namespace-scope
+       enumeration types.
+       * pt.c (tsubst_copy): Adjust handling of CONST_DECLs accordingly.
+       (tsubst_enum): Tidy.
+
+       * Make-lang.in (typeck.o): Depend on convert.h.
+       (class.o): Likewise.
+       (rtti.o): Likewise.
+       * call.c: Include convert.h.
+       (convert_arg_to_ellipsis): Use convert_to_real.
+       * class.c: Include convert.h.
+       (build_base_path): Use convert_to_integer.
+       * rtti.c: Include convert.h.
+       (build_headof): Use convert_to_integer.
+       * typeck.c: Include convert.h.
+       (decay_conversion): Use convert_to_integer.
+       (build_unary_op): Use build_nop.
+       (get_delta_difference): Use convert_to_integer.
+       (build_ptrmemfunc): Avoid unncessary conversions.
+
 Mon Jul 28 23:55:10 CEST 2003  Jan Hubicka  <jh@suse.cz>
 
        * decl2.c (mark_member_pointers): Verify that member pointer points to
index d16a5bcb02e14c5153b0b9d5474742b9188dd100..05a3a8c4b4429a623271699b9f35009a8d4c2d4b 100644 (file)
@@ -244,10 +244,10 @@ cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H
 cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \
    diagnostic.h
 cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
-   diagnostic.h
-cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H)
+   diagnostic.h convert.h
+cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H) convert.h
 cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \
-     diagnostic.h intl.h gt-cp-call.h
+     diagnostic.h intl.h gt-cp-call.h convert.h
 cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
 cp/init.o: cp/init.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
   except.h
@@ -258,7 +258,7 @@ cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) stack.h flags.h toplev.h $(RTL_H)
 cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \
   insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H)
 cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H)
-cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h
+cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h convert.h
 cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h toplev.h \
   cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h
 cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
index 7e3302fa0f7d02e0097947b3a0ba6812669d621f..e8b2902738780f4a565c1ce0728e9f3eede10eac 100644 (file)
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "diagnostic.h"
 #include "intl.h"
+#include "convert.h"
 
 static tree build_field_call (tree, tree, tree);
 static struct z_candidate * tourney (struct z_candidate *);
@@ -653,8 +654,7 @@ standard_conversion (tree to, tree from, tree expr)
       conv = build_conv (STD_CONV, to, conv);
       ICS_BAD_FLAG (conv) = 1;
     }
-  else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE
-          && TYPE_PRECISION (to) == TYPE_PRECISION (from))
+  else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE)
     {
       /* For backwards brain damage compatibility, allow interconversion of
         enums and integers with a pedwarn.  */
@@ -4201,7 +4201,7 @@ convert_arg_to_ellipsis (tree arg)
   if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
       && (TYPE_PRECISION (TREE_TYPE (arg))
          < TYPE_PRECISION (double_type_node)))
-    arg = cp_convert (double_type_node, arg);
+    arg = convert_to_real (double_type_node, arg);
   else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
     arg = perform_integral_promotions (arg);
 
index d2fb90283dbcfb61ff3350a0f6980ac4e2952679..b447f7013ee067775604499deba53f8580d280ed 100644 (file)
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "lex.h"
 #include "target.h"
+#include "convert.h"
 
 /* The number of nested classes being processed.  If we are not in the
    scope of any class, this is zero.  */
@@ -328,8 +329,9 @@ build_base_path (enum tree_code code,
       v_offset = build_indirect_ref (v_offset, NULL);
       TREE_CONSTANT (v_offset) = 1;
 
-      offset = cp_convert (ptrdiff_type_node,
-                          size_diffop (offset, BINFO_OFFSET (v_binfo)));
+      offset = convert_to_integer (ptrdiff_type_node,
+                                  size_diffop (offset, 
+                                               BINFO_OFFSET (v_binfo)));
 
       if (!integer_zerop (offset))
        v_offset = build (code, ptrdiff_type_node, v_offset, offset);
index 4e6da3f5f33d8e7b365263653674909b2f5ae32a..583b87417443c45b0a52e98b237254fbba320e4a 100644 (file)
@@ -13028,7 +13028,9 @@ start_enum (tree name)
 void
 finish_enum (tree enumtype)
 {
-  tree pair;
+  tree values;
+  tree decl;
+  tree value;
   tree minnode;
   tree maxnode;
   tree t;
@@ -13036,6 +13038,8 @@ finish_enum (tree enumtype)
   int lowprec;
   int highprec; 
   int precision;
+  integer_type_kind itk;
+  tree underlying_type;
 
   /* We built up the VALUES in reverse order.  */
   TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
@@ -13046,21 +13050,25 @@ finish_enum (tree enumtype)
      works.  */
   if (processing_template_decl)
     {
-      for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
-       TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+      for (values = TYPE_VALUES (enumtype); 
+          values; 
+          values = TREE_CHAIN (values))
+       TREE_TYPE (TREE_VALUE (values)) = enumtype;
       if (at_function_scope_p ())
        add_stmt (build_min (TAG_DEFN, enumtype));
       return;
     }
 
+  /* Determine the minimum and maximum values of the enumerators.  */
   if (TYPE_VALUES (enumtype))
     {
       minnode = maxnode = NULL_TREE;
 
-      for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+      for (values = TYPE_VALUES (enumtype); 
+          values; 
+          values = TREE_CHAIN (values))
        {
-         tree decl = TREE_VALUE (pair);
-         tree value = DECL_INITIAL (decl);
+         decl = TREE_VALUE (values);
 
          /* [dcl.enum]: Following the closing brace of an enum-specifier,
             each enumerator has the type of its enumeration.  Prior to the
@@ -13068,6 +13076,8 @@ finish_enum (tree enumtype)
             initializing value.  */
          TREE_TYPE (decl) = enumtype;
 
+         /* Update the minimum and maximum values, if appropriate.  */
+         value = DECL_INITIAL (decl);
          /* Figure out what the minimum and maximum values of the
             enumerators are.  */
          if (!minnode)
@@ -13086,13 +13096,13 @@ finish_enum (tree enumtype)
              value = DECL_INITIAL (decl) = copy_node (value);
              TREE_TYPE (value) = enumtype;
            }
-
-         /* In addition, transform the TYPE_VALUES list to contain the
-            values, rather than the CONST_DECLs for them.  */
-         TREE_VALUE (pair) = value;
        }
     }
   else
+    /* [dcl.enum]
+
+       If the enumerator-list is empty, the underlying type is as if
+       the enumeration had a single enumerator with value 0.  */
     minnode = maxnode = integer_zero_node;
 
   /* Compute the number of bits require to represent all values of the
@@ -13104,35 +13114,75 @@ finish_enum (tree enumtype)
   highprec = min_precision (maxnode, unsignedp);
   precision = MAX (lowprec, highprec);
 
-  /* DR 377
-       
-     IF no integral type can represent all the enumerator values, the
-     enumeration is ill-formed.  */
-  if (precision > TYPE_PRECISION (long_long_integer_type_node))
+  /* Determine the underlying type of the enumeration.
+
+       [dcl.enum]
+
+       The underlying type of an enumeration is an integral type that
+       can represent all the enumerator values defined in the
+       enumeration.  It is implementation-defined which integral type is
+       used as the underlying type for an enumeration except that the
+       underlying type shall not be larger than int unless the value of
+       an enumerator cannot fit in an int or unsigned int.  
+
+     We use "int" or an "unsigned int" as the underlying type, even if
+     a smaller integral type would work, unless the user has
+     explicitly requested that we use the smallest possible type.  */
+  for (itk = (flag_short_enums ? itk_char : itk_int); 
+       itk != itk_none; 
+       itk++)
     {
+      underlying_type = integer_types[itk];
+      if (TYPE_PRECISION (underlying_type) >= precision
+         && TREE_UNSIGNED (underlying_type) == unsignedp)
+       break;
+    }
+  if (itk == itk_none)
+    {
+      /* DR 377
+
+        IF no integral type can represent all the enumerator values, the
+        enumeration is ill-formed.  */
       error ("no integral type can represent all of the enumerator values "
             "for `%T'", enumtype);
       precision = TYPE_PRECISION (long_long_integer_type_node);
+      underlying_type = integer_types[itk_unsigned_long_long];
     }
 
-  /* Compute the minium and maximum values for the type, the size of
-     the type, and so forth.  */
-  TYPE_PRECISION (enumtype) = precision;
-  TYPE_SIZE (enumtype) = NULL_TREE;
-  if (unsignedp)
-    fixup_unsigned_type (enumtype);
-  else
-    fixup_signed_type (enumtype);
+  /* Compute the minium and maximum values for the type.  
 
-  /* We use "int" or "unsigned int" as the underlying type, unless all
-     the values will not fit or the user has requested that we try to
-     use shorter types where possible.  */
-  if (precision < TYPE_PRECISION (integer_type_node)
-      && !flag_short_enums)
-    {
-      TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
-      TYPE_SIZE (enumtype) = NULL_TREE;
-      layout_type (enumtype);
+     [dcl.enum]
+
+     For an enumeration where emin is the smallest enumerator and emax
+     is the largest, the values of the enumeration are the values of the
+     underlying type in the range bmin to bmax, where bmin and bmax are,
+     respectively, the smallest and largest values of the smallest bit-
+     field that can store emin and emax.  */
+  TYPE_PRECISION (enumtype) = precision;
+  set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
+
+  /* [dcl.enum]
+     
+     The value of sizeof() applied to an enumeration type, an object
+     of an enumeration type, or an enumerator, is the value of sizeof()
+     applied to the underlying type.  */
+  TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type);
+  TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type);
+  TYPE_MODE (enumtype) = TYPE_MODE (underlying_type);
+  TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
+  TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
+  TREE_UNSIGNED (enumtype) = TREE_UNSIGNED (underlying_type);
+
+  /* Convert each of the enumerators to the type of the underlying
+     type of the enumeration.  */
+  for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
+    {
+      decl = TREE_VALUE (values);
+      value = perform_implicit_conversion (underlying_type,
+                                          DECL_INITIAL (decl));
+      TREE_TYPE (value) = enumtype;
+      DECL_INITIAL (decl) = value;
+      TREE_VALUE (values) = value;
     }
 
   /* Fix up all variant types of this enum type.  */
@@ -13215,6 +13265,8 @@ build_enumerator (tree name, tree value, tree enumtype)
 
   /* C++ associates enums with global, function, or class declarations.  */
   context = current_scope ();
+  if (!context)
+    context = current_namespace;
 
   /* Build the actual enumeration constant.  Note that the enumeration
     constants have the type of their initializers until the
@@ -13246,8 +13298,8 @@ build_enumerator (tree name, tree value, tree enumtype)
 
   if (context && context == current_class_type)
     /* In something like `struct S { enum E { i = 7 }; };' we put `i'
-      on the TYPE_FIELDS list for `S'.  (That's so that you can say
-      things like `S::i' later.)  */
+       on the TYPE_FIELDS list for `S'.  (That's so that you can say
+       things like `S::i' later.)  */
     finish_member_declaration (decl);
   else
     pushdecl (decl);
index 31bde1a9a0cedd4e81263fe8428a59d268b841fb..8f10de49065d5775737794714509c205fb5dc9a9 100644 (file)
@@ -7214,8 +7214,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
        if (DECL_TEMPLATE_PARM_P (t))
          return tsubst_copy (DECL_INITIAL (t), args, complain, in_decl);
-       if (!DECL_CONTEXT (t))
-         /* This is a global enumeration constant.  */
+       /* There is no need to substitute into namespace-scope
+          enumerators.  */
+       if (DECL_NAMESPACE_SCOPE_P (t))
          return t;
 
        /* Unfortunately, we cannot just call lookup_name here.
@@ -11151,18 +11152,20 @@ tsubst_enum (tree tag, tree newtag, tree args)
   for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
     {
       tree value;
-      
+      tree decl;
+
+      decl = TREE_VALUE (e);
       /* Note that in a template enum, the TREE_VALUE is the
         CONST_DECL, not the corresponding INTEGER_CST.  */
-      value = tsubst_expr (DECL_INITIAL (TREE_VALUE (e)), 
+      value = tsubst_expr (DECL_INITIAL (decl), 
                           args, tf_error | tf_warning,
                           NULL_TREE);
 
       /* Give this enumeration constant the correct access.  */
-      set_current_access_from_decl (TREE_VALUE (e));
+      set_current_access_from_decl (decl);
 
       /* Actually build the enumerator itself.  */
-      build_enumerator (TREE_PURPOSE (e), value, newtag); 
+      build_enumerator (DECL_NAME (decl), value, newtag); 
     }
 
   finish_enum (newtag);
index fdad47d9cc4ef05abde8c13c0c6be59ccd93a51e..baaff74d68b11df5f9844fcfc1b243d9fe59371f 100644 (file)
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "assert.h"
 #include "toplev.h"
+#include "convert.h"
 
 /* C++ returns type information to the user in struct type_info
    objects. We also use type information to implement dynamic_cast and
@@ -159,8 +160,8 @@ build_headof (tree exp)
 
   type = build_qualified_type (ptr_type_node, 
                               cp_type_quals (TREE_TYPE (exp)));
-  return build (PLUS_EXPR, type, exp,
-               cp_convert (ptrdiff_type_node, offset));
+  return build (PLUS_EXPR, type, exp, 
+               convert_to_integer (ptrdiff_type_node, offset));
 }
 
 /* Get a bad_cast node for the program to throw...
index ec6765b28b06e67067c2294ea040d6ed23cace32..00fa013b69a0e34d6a3f8ceddcc69dd655e6d7fc 100644 (file)
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "diagnostic.h"
 #include "target.h"
+#include "convert.h"
 
 static tree convert_for_assignment (tree, tree, const char *, tree, int);
 static tree cp_pointer_int_sum (enum tree_code, tree, tree);
@@ -1291,20 +1292,8 @@ decay_conversion (tree exp)
       tree ptrtype;
 
       if (TREE_CODE (exp) == INDIRECT_REF)
-       {
-         /* Stripping away the INDIRECT_REF is not the right
-            thing to do for references...  */
-         tree inner = TREE_OPERAND (exp, 0);
-         if (TREE_CODE (TREE_TYPE (inner)) == REFERENCE_TYPE)
-           {
-             inner = build1 (CONVERT_EXPR,
-                             build_pointer_type (TREE_TYPE
-                                                 (TREE_TYPE (inner))),
-                             inner);
-             TREE_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0));
-           }
-         return cp_convert (build_pointer_type (TREE_TYPE (type)), inner);
-       }
+       return build_nop (build_pointer_type (TREE_TYPE (type)), 
+                         TREE_OPERAND (exp, 0));
 
       if (TREE_CODE (exp) == COMPOUND_EXPR)
        {
@@ -4007,8 +3996,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
                                      ba_check, NULL);
            
            rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
-           rval = build1 (NOP_EXPR, argtype, rval);
-           TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
+           rval = build_nop (argtype, rval);
            addr = fold (build (PLUS_EXPR, argtype, rval,
                                cp_convert (argtype, byte_position (field))));
          }
@@ -5192,8 +5180,9 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 
 \f
 /* Get difference in deltas for different pointer to member function
-   types.  Return integer_zero_node, if FROM cannot be converted to a
-   TO type.  If FORCE is true, then allow reverse conversions as well.
+   types.  Returns an integer constant of type PTRDIFF_TYPE_NODE.  If
+   the conversion is invalid, the constant is zero.  If FORCE is true,
+   then allow reverse conversions as well.
 
    Note that the naming of FROM and TO is kind of backwards; the return
    value is what we add to a TO in order to get a FROM.  They are named
@@ -5203,7 +5192,6 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 static tree
 get_delta_difference (tree from, tree to, int force)
 {
-  tree delta = integer_zero_node;
   tree binfo;
   tree virt_binfo;
   base_kind kind;
@@ -5212,7 +5200,7 @@ get_delta_difference (tree from, tree to, int force)
   if (kind == bk_inaccessible || kind == bk_ambig)
     {
       error ("   in pointer to member function conversion");
-      return delta;
+      goto error;
     }
   if (!binfo)
     {
@@ -5220,44 +5208,38 @@ get_delta_difference (tree from, tree to, int force)
        {
          error_not_base_type (from, to);
          error ("   in pointer to member conversion");
-         return delta;
+         goto error;
        }
       binfo = lookup_base (from, to, ba_check, &kind);
-      if (binfo == 0)
-       return delta;
+      if (!binfo)
+       goto error;
       virt_binfo = binfo_from_vbase (binfo);
-      
       if (virt_binfo)
         {
           /* This is a reinterpret cast, we choose to do nothing.  */
           warning ("pointer to member cast via virtual base `%T'",
                   BINFO_TYPE (virt_binfo));
-          return delta;
+         goto error;
         }
-      delta = BINFO_OFFSET (binfo);
-      delta = cp_convert (ptrdiff_type_node, delta);
-      delta = cp_build_binary_op (MINUS_EXPR,
-                                integer_zero_node,
-                                delta);
-
-      return delta;
+      return convert_to_integer (ptrdiff_type_node, 
+                                size_diffop (size_zero_node,
+                                             BINFO_OFFSET (binfo)));
     }
 
   virt_binfo = binfo_from_vbase (binfo);
-  if (virt_binfo)
-    {
-      /* This is a reinterpret cast, we choose to do nothing.  */
-      if (force)
-        warning ("pointer to member cast via virtual base `%T'",
-                BINFO_TYPE (virt_binfo));
-      else
-       error ("pointer to member conversion via virtual base `%T'",
-              BINFO_TYPE (virt_binfo));
-      return delta;
-    }
-  delta = BINFO_OFFSET (binfo);
+  if (!virt_binfo)
+    return convert_to_integer (ptrdiff_type_node, BINFO_OFFSET (binfo));
+
+  /* This is a reinterpret cast, we choose to do nothing.  */
+  if (force)
+    warning ("pointer to member cast via virtual base `%T'",
+            BINFO_TYPE (virt_binfo));
+  else
+    error ("pointer to member conversion via virtual base `%T'",
+          BINFO_TYPE (virt_binfo));
 
-  return cp_convert (ptrdiff_type_node, delta);
+ error:
+  return convert_to_integer(ptrdiff_type_node, integer_zero_node);
 }
 
 /* Return a constructor for the pointer-to-member-function TYPE using
@@ -5355,7 +5337,7 @@ build_ptrmemfunc (tree type, tree pfn, int force)
        }
 
       /* Just adjust the DELTA field.  */
-      delta = cp_convert (ptrdiff_type_node, delta);
+      my_friendly_assert (TREE_TYPE (delta) == ptrdiff_type_node, 20030727);
       if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
        n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node);
       delta = cp_build_binary_op (PLUS_EXPR, delta, n);
index e2395c451c54706efe9ad93cf532c56ecab702e5..54e6a56de9904c3bae5643b89d5eb6621173c7a7 100644 (file)
@@ -1957,6 +1957,58 @@ set_sizetype (tree type)
   sizetype_set = 1;
 }
 \f
+/* TYPE is an integral type, i.e., an INTEGRAL_TYPE, ENUMERAL_TYPE,
+   BOOLEAN_TYPE, or CHAR_TYPE.  Set TYPE_MIN_VALUE and TYPE_MAX_VALUE
+   for TYPE, based on the PRECISION and whether or not the TYPE
+   IS_UNSIGNED.  PRECISION need not correspond to a width supported
+   natively by the hardware; for example, on a machine with 8-bit,
+   16-bit, and 32-bit register modes, PRECISION might be 7, 23, or
+   61.  */
+
+void
+set_min_and_max_values_for_integral_type (tree type,
+                                         int precision,
+                                         bool is_unsigned)
+{
+  tree min_value;
+  tree max_value;
+
+  if (is_unsigned)
+    {
+      min_value = build_int_2 (0, 0);
+      max_value 
+       = build_int_2 (precision - HOST_BITS_PER_WIDE_INT >= 0
+                      ? -1 : ((HOST_WIDE_INT) 1 << precision) - 1,
+                      precision - HOST_BITS_PER_WIDE_INT > 0
+                      ? ((unsigned HOST_WIDE_INT) ~0
+                         >> (HOST_BITS_PER_WIDE_INT
+                             - (precision - HOST_BITS_PER_WIDE_INT)))
+                      : 0);
+    }
+  else
+    {
+      min_value 
+       = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
+                       ? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)),
+                      (((HOST_WIDE_INT) (-1)
+                        << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
+                            ? precision - HOST_BITS_PER_WIDE_INT - 1
+                            : 0))));    
+      max_value
+       = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
+                       ? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1),
+                      (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
+                       ? (((HOST_WIDE_INT) 1
+                           << (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1
+                       : 0));
+    }
+
+  TREE_TYPE (min_value) = type;
+  TREE_TYPE (max_value) = type;
+  TYPE_MIN_VALUE (type) = min_value;
+  TYPE_MAX_VALUE (type) = max_value;
+}
+
 /* Set the extreme values of TYPE based on its precision in bits,
    then lay it out.  Used when make_signed_type won't do
    because the tree code is not INTEGER_TYPE.
@@ -1973,23 +2025,8 @@ fixup_signed_type (tree type)
   if (precision > HOST_BITS_PER_WIDE_INT * 2)
     precision = HOST_BITS_PER_WIDE_INT * 2;
 
-  TYPE_MIN_VALUE (type)
-    = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
-                   ? 0 : (HOST_WIDE_INT) (-1) << (precision - 1)),
-                  (((HOST_WIDE_INT) (-1)
-                    << (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
-                        ? precision - HOST_BITS_PER_WIDE_INT - 1
-                        : 0))));
-  TYPE_MAX_VALUE (type)
-    = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
-                   ? -1 : ((HOST_WIDE_INT) 1 << (precision - 1)) - 1),
-                  (precision - HOST_BITS_PER_WIDE_INT - 1 > 0
-                   ? (((HOST_WIDE_INT) 1
-                       << (precision - HOST_BITS_PER_WIDE_INT - 1))) - 1
-                   : 0));
-
-  TREE_TYPE (TYPE_MIN_VALUE (type)) = type;
-  TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
+  set_min_and_max_values_for_integral_type (type, precision, 
+                                           /*is_unsigned=*/false);
 
   /* Lay out the type: set its alignment, size, etc.  */
   layout_type (type);
@@ -2010,17 +2047,8 @@ fixup_unsigned_type (tree type)
   if (precision > HOST_BITS_PER_WIDE_INT * 2)
     precision = HOST_BITS_PER_WIDE_INT * 2;
 
-  TYPE_MIN_VALUE (type) = build_int_2 (0, 0);
-  TYPE_MAX_VALUE (type)
-    = build_int_2 (precision - HOST_BITS_PER_WIDE_INT >= 0
-                  ? -1 : ((HOST_WIDE_INT) 1 << precision) - 1,
-                  precision - HOST_BITS_PER_WIDE_INT > 0
-                  ? ((unsigned HOST_WIDE_INT) ~0
-                     >> (HOST_BITS_PER_WIDE_INT
-                         - (precision - HOST_BITS_PER_WIDE_INT)))
-                  : 0);
-  TREE_TYPE (TYPE_MIN_VALUE (type)) = type;
-  TREE_TYPE (TYPE_MAX_VALUE (type)) = type;
+  set_min_and_max_values_for_integral_type (type, precision, 
+                                           /*is_unsigned=*/true);
 
   /* Lay out the type: set its alignment, size, etc.  */
   layout_type (type);
index e933fab16ac2fbbbd6b079026e26e9f915a36ca0..f0171688fcbc55b358e7edd7df790b33185744bc 100644 (file)
@@ -1,3 +1,9 @@
+2003-07-28  Alexandre Oliva <aoliva@redhat.com>
+
+       PR c++/11667
+       * g++.dg/init/enum2.C: New test.
+       * g++.dg/template/overload1.C: Add "-w" option.
+       
 2003-07-28    <hp@bitrange.com>
 
        * gcc.dg/Wdeclaration-after-statement-1.c,
diff --git a/gcc/testsuite/g++.dg/init/enum2.C b/gcc/testsuite/g++.dg/init/enum2.C
new file mode 100644 (file)
index 0000000..dea7dc1
--- /dev/null
@@ -0,0 +1,9 @@
+#include <limits.h>
+enum test {
+  z = 0,
+  c = UINT_MAX + 1LL
+} x = z;
+
+int main() {
+  return x != z;
+}
index 404fc2dfed5d173f31a8a62780e9b7f900980bbd..2225fecf730284e8e81e660ace8671f1897ccb4b 100644 (file)
@@ -1,3 +1,4 @@
+// { dg-options "-w" }
 // PR c++/9420
 // Bug: We were instantiating B<int> during overload resolution for E<0.
 // This is wrong; the contents of B<int> are not relevant, since we can't
index 01cca269a338b02d299e998aa74ad1085b53f82d..e44af15a877e371bf3cd94aa27c2d3d84b4f7f96 100644 (file)
@@ -2909,6 +2909,7 @@ extern void output_inline_function (tree);
 extern void set_decl_origin_self (tree);
 
 /* In stor-layout.c */
+extern void set_min_and_max_values_for_integral_type (tree, int, bool);
 extern void fixup_signed_type (tree);
 extern void internal_reference_types (void);