From: Mark Mitchell Date: Tue, 29 Jul 2003 01:14:24 +0000 (+0000) Subject: re PR c++/11667 (wider-than-int enums never compare equal to 0) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7b6d72fcfbd0aa2bb05d81afcdcf5e4c6027b2e8;p=gcc.git re PR c++/11667 (wider-than-int enums never compare equal to 0) 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c3e8f266a92..c3059e557af 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2003-07-28 Mark Mitchell + + 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 * c-decl.c: Update commentary, adjust blank lines throughout. diff --git a/gcc/c-common.c b/gcc/c-common.c index c579b16f37c..8dea43bb028 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -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); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index abbe9ccbbc3..64068a2cab5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,30 @@ +2003-07-28 Mark Mitchell + + 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 * decl2.c (mark_member_pointers): Verify that member pointer points to diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index d16a5bcb02e..05a3a8c4b44 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -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 \ diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7e3302fa0f7..e8b29027387 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index d2fb90283db..b447f7013ee 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 4e6da3f5f33..583b8741744 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 31bde1a9a0c..8f10de49065 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index fdad47d9cc4..baaff74d68b 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -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... diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index ec6765b28b0..00fa013b69a 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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) /* 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); diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index e2395c451c5..54e6a56de99 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -1957,6 +1957,58 @@ set_sizetype (tree type) sizetype_set = 1; } +/* 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e933fab16ac..f0171688fcb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2003-07-28 Alexandre Oliva + + PR c++/11667 + * g++.dg/init/enum2.C: New test. + * g++.dg/template/overload1.C: Add "-w" option. + 2003-07-28 * 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 index 00000000000..dea7dc17be0 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/enum2.C @@ -0,0 +1,9 @@ +#include +enum test { + z = 0, + c = UINT_MAX + 1LL +} x = z; + +int main() { + return x != z; +} diff --git a/gcc/testsuite/g++.dg/template/overload1.C b/gcc/testsuite/g++.dg/template/overload1.C index 404fc2dfed5..2225fecf730 100644 --- a/gcc/testsuite/g++.dg/template/overload1.C +++ b/gcc/testsuite/g++.dg/template/overload1.C @@ -1,3 +1,4 @@ +// { dg-options "-w" } // PR c++/9420 // Bug: We were instantiating B during overload resolution for E<0. // This is wrong; the contents of B are not relevant, since we can't diff --git a/gcc/tree.h b/gcc/tree.h index 01cca269a33..e44af15a877 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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);