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
This commit is contained in:
parent
92a6fb2cf2
commit
7b6d72fcfb
15 changed files with 253 additions and 128 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
118
gcc/cp/decl.c
118
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)
|
||||
[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))
|
||||
{
|
||||
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
|
||||
TYPE_SIZE (enumtype) = NULL_TREE;
|
||||
layout_type (enumtype);
|
||||
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);
|
||||
|
|
15
gcc/cp/pt.c
15
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);
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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));
|
||||
|
||||
return cp_convert (ptrdiff_type_node, delta);
|
||||
/* 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));
|
||||
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
9
gcc/testsuite/g++.dg/init/enum2.C
Normal file
9
gcc/testsuite/g++.dg/init/enum2.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include <limits.h>
|
||||
enum test {
|
||||
z = 0,
|
||||
c = UINT_MAX + 1LL
|
||||
} x = z;
|
||||
|
||||
int main() {
|
||||
return x != z;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue