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> 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 PR c++/48599
* decl.c (create_array_type_for_decl): Complain about array of auto. * 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) ...@@ -12190,9 +12190,13 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
tree prev_value; tree prev_value;
bool overflowed; bool overflowed;
/* The next value is the previous value plus one. /* C++03 7.2/4: If no initializer is specified for the first
add_double doesn't know the type of the target expression, enumerator, the type is an unspecified integral
so we must check with int_fits_type_p as well. */ 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))); prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
if (error_operand_p (prev_value)) if (error_operand_p (prev_value))
value = error_mark_node; value = error_mark_node;
...@@ -12201,9 +12205,34 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc) ...@@ -12201,9 +12205,34 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
overflowed = add_double (TREE_INT_CST_LOW (prev_value), overflowed = add_double (TREE_INT_CST_LOW (prev_value),
TREE_INT_CST_HIGH (prev_value), TREE_INT_CST_HIGH (prev_value),
1, 0, &lo, &hi); 1, 0, &lo, &hi);
value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi); if (!overflowed)
overflowed {
|= !int_fits_type_p (value, TREE_TYPE (prev_value)); 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) if (overflowed)
{ {
......
2011-05-25 Jason Merrill <jason@redhat.com> 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/auto24.C: New.
* g++.dg/cpp0x/error4.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-do assemble }
// { dg-options "-pedantic-errors" }
// Bug: g++ doesn't notice the overflow in the enum values. // Bug: g++ doesn't notice the overflow in the enum values.
#include <limits.h> #include <limits.h>
...@@ -7,5 +8,5 @@ enum COLOR ...@@ -7,5 +8,5 @@ enum COLOR
{ {
red, red,
green = ULONG_MAX, 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