Commit 26513391 by Jason Merrill Committed by Jason Merrill

re PR c++/48536 ([C++0x] Automatic Enumerator Incrementation is not compliant with Clause 7.2/5)

	PR c++/48536
	* decl.c (build_enumerator): If incremented enumerator won't fit in
	previous integral type, find one it will fit in.

From-SVN: r174258
parent 5df0c0c7
2011-05-25 Jason Merrill <jason@redhat.com>
PR c++/48536
* decl.c (build_enumerator): If incremented enumerator won't fit in
previous integral type, find one it will fit in.
PR c++/48599
* decl.c (create_array_type_for_decl): Complain about array of auto.
......
......@@ -12190,9 +12190,13 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
tree prev_value;
bool overflowed;
/* The next value is the previous value plus one.
add_double doesn't know the type of the target expression,
so we must check with int_fits_type_p as well. */
/* C++03 7.2/4: If no initializer is specified for the first
enumerator, the type is an unspecified integral
type. Otherwise the type is the same as the type of the
initializing value of the preceding enumerator unless the
incremented value is not representable in that type, in
which case the type is an unspecified integral type
sufficient to contain the incremented value. */
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
if (error_operand_p (prev_value))
value = error_mark_node;
......@@ -12201,9 +12205,34 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
overflowed = add_double (TREE_INT_CST_LOW (prev_value),
TREE_INT_CST_HIGH (prev_value),
1, 0, &lo, &hi);
value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
overflowed
|= !int_fits_type_p (value, TREE_TYPE (prev_value));
if (!overflowed)
{
double_int di;
tree type = TREE_TYPE (prev_value);
bool pos = (TYPE_UNSIGNED (type) || hi >= 0);
di.low = lo; di.high = hi;
if (!double_int_fits_to_tree_p (type, di))
{
unsigned int itk;
for (itk = itk_int; itk != itk_none; itk++)
{
type = integer_types[itk];
if (type != NULL_TREE
&& (pos || !TYPE_UNSIGNED (type))
&& double_int_fits_to_tree_p (type, di))
break;
}
if (type && cxx_dialect < cxx0x
&& itk > itk_unsigned_long)
pedwarn (input_location, OPT_Wlong_long, pos ? "\
incremented enumerator value is too large for %<unsigned long%>" : "\
incremented enumerator value is too large for %<long%>");
}
if (type == NULL_TREE)
overflowed = true;
else
value = double_int_to_tree (type, di);
}
if (overflowed)
{
......
2011-05-25 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/enum17.C: New.
* g++.old-deja/g++.jason/rfg10.C: Adjust.
* g++.dg/cpp0x/auto24.C: New.
* g++.dg/cpp0x/error4.C: New.
......
// PR c++/48536
// { dg-options "-std=c++0x -pedantic-errors" }
#include <climits>
// According to C++11 / Clause 7.2/5 the following enumeration is
// well-formed. It is also well-formed in C++03 if UINT_MAX < ULONG_MAX,
// but C++11 adds long long.
enum Enum_Inc { EI_1=UINT_MAX, EI_2 }; // #1
// It is not equivalent to the following.
enum Enum_Inc2 { FI_1=UINT_MAX, FI_2=FI_1+1 }; // #2
#define SA(X) static_assert(X,#X)
SA (EI_2 != 0);
SA (FI_2 == 0);
// { dg-do assemble }
// { dg-options "-pedantic-errors" }
// Bug: g++ doesn't notice the overflow in the enum values.
#include <limits.h>
......@@ -7,5 +8,5 @@ enum COLOR
{
red,
green = ULONG_MAX,
blue // { dg-error "overflow in enumeration" }
blue // { dg-error "too large for .unsigned long" }
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment