Commit 05d6cb1a by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/61414 (enum class bitfield size-checking needs a separate warning flag controlling it)

	PR c++/61414
	* c-attribs.c (handle_mode_attribute): Add mode attribute to
	ENUMERAL_TYPEs.

	* class.c (enum_to_min_precision): New hash_map.
	(enum_min_precision): New function.
	(check_bitfield_decl): Use it.

	* g++.dg/cpp0x/enum23.C: Remove xfail.
	* g++.dg/cpp0x/enum28.C: New test.

From-SVN: r278736
parent 1f7ed00e
2019-11-26 Jakub Jelinek <jakub@redhat.com>
PR c++/61414
* c-attribs.c (handle_mode_attribute): Add mode attribute to
ENUMERAL_TYPEs.
2019-11-25 Joseph Myers <joseph@codesourcery.com> 2019-11-25 Joseph Myers <joseph@codesourcery.com>
PR c/91985 PR c/91985
......
...@@ -1866,6 +1866,7 @@ handle_mode_attribute (tree *node, tree name, tree args, ...@@ -1866,6 +1866,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
typefm = make_signed_type (TYPE_PRECISION (typefm)); typefm = make_signed_type (TYPE_PRECISION (typefm));
TREE_TYPE (typefm) = type; TREE_TYPE (typefm) = type;
} }
*no_add_attrs = false;
} }
else if (VECTOR_MODE_P (mode) else if (VECTOR_MODE_P (mode)
? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm)) ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
......
2019-11-26 Jakub Jelinek <jakub@redhat.com>
PR c++/61414
* class.c (enum_to_min_precision): New hash_map.
(enum_min_precision): New function.
(check_bitfield_decl): Use it.
2019-11-25 Paolo Carlini <paolo.carlini@oracle.com> 2019-11-25 Paolo Carlini <paolo.carlini@oracle.com>
* typeck.c (cp_build_indirect_ref_1): Add location_t parameter * typeck.c (cp_build_indirect_ref_1): Add location_t parameter
......
...@@ -3265,6 +3265,60 @@ add_implicitly_declared_members (tree t, tree* access_decls, ...@@ -3265,6 +3265,60 @@ add_implicitly_declared_members (tree t, tree* access_decls,
} }
} }
/* Cache of enum_min_precision values. */
static GTY((deletable)) hash_map<tree, int> *enum_to_min_precision;
/* Return the minimum precision of a bit-field needed to store all
enumerators of ENUMERAL_TYPE TYPE. */
static int
enum_min_precision (tree type)
{
type = TYPE_MAIN_VARIANT (type);
/* For unscoped enums without fixed underlying type and without mode
attribute we can just use precision of the underlying type. */
if (UNSCOPED_ENUM_P (type)
&& !ENUM_FIXED_UNDERLYING_TYPE_P (type)
&& !lookup_attribute ("mode", TYPE_ATTRIBUTES (type)))
return TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type));
if (enum_to_min_precision == NULL)
enum_to_min_precision = hash_map<tree, int>::create_ggc (37);
bool existed;
int prec = enum_to_min_precision->get_or_insert (type, &existed);
if (existed)
return prec;
tree minnode, maxnode;
if (TYPE_VALUES (type))
{
minnode = maxnode = NULL_TREE;
for (tree values = TYPE_VALUES (type);
values; values = TREE_CHAIN (values))
{
tree decl = TREE_VALUE (values);
tree value = DECL_INITIAL (decl);
if (value == error_mark_node)
value = integer_zero_node;
if (!minnode)
minnode = maxnode = value;
else if (tree_int_cst_lt (maxnode, value))
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
}
}
else
minnode = maxnode = integer_zero_node;
signop sgn = tree_int_cst_sgn (minnode) >= 0 ? UNSIGNED : SIGNED;
int lowprec = tree_int_cst_min_precision (minnode, sgn);
int highprec = tree_int_cst_min_precision (maxnode, sgn);
prec = MAX (lowprec, highprec);
return prec;
}
/* FIELD is a bit-field. We are finishing the processing for its /* FIELD is a bit-field. We are finishing the processing for its
enclosing type. Issue any appropriate messages and set appropriate enclosing type. Issue any appropriate messages and set appropriate
flags. Returns false if an error has been diagnosed. */ flags. Returns false if an error has been diagnosed. */
...@@ -3326,7 +3380,7 @@ check_bitfield_decl (tree field) ...@@ -3326,7 +3380,7 @@ check_bitfield_decl (tree field)
"width of %qD exceeds its type", field); "width of %qD exceeds its type", field);
else if (TREE_CODE (type) == ENUMERAL_TYPE) else if (TREE_CODE (type) == ENUMERAL_TYPE)
{ {
int prec = TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type)); int prec = enum_min_precision (type);
if (compare_tree_int (w, prec) < 0) if (compare_tree_int (w, prec) < 0)
warning_at (DECL_SOURCE_LOCATION (field), 0, warning_at (DECL_SOURCE_LOCATION (field), 0,
"%qD is too small to hold all values of %q#T", "%qD is too small to hold all values of %q#T",
......
2019-11-26 Jakub Jelinek <jakub@redhat.com> 2019-11-26 Jakub Jelinek <jakub@redhat.com>
PR c++/61414
* g++.dg/cpp0x/enum23.C: Remove xfail.
* g++.dg/cpp0x/enum28.C: New test.
PR tree-optimization/92644 PR tree-optimization/92644
* g++.dg/opt/pr92644.C: New test. * g++.dg/opt/pr92644.C: New test.
......
...@@ -5,5 +5,5 @@ enum class MyEnum { A = 1 }; ...@@ -5,5 +5,5 @@ enum class MyEnum { A = 1 };
struct MyClass struct MyClass
{ {
MyEnum Field1 : 3; // { dg-bogus "warning: 'MyClass::Field1' is too small" "" { xfail *-*-* } } MyEnum Field1 : 3; // { dg-bogus "warning: 'MyClass::Field1' is too small" }
}; };
// PR c++/61414
// { dg-do compile { target c++11 } }
enum C { C0 = -4, C1 = 3 };
enum D { D0 = 0, D1 = 15 };
enum class E { E0 = -4, E1 = 3 };
enum F : unsigned { F0 = 0, F1 = 15 };
enum __attribute__((__mode__ (__QI__))) G { G0 = -4, G1 = 3 };
enum __attribute__((__mode__ (__HI__))) H { H0 = 0, H1 = 15 };
struct S
{
C a : 2; // { dg-warning "'S::a' is too small to hold all values of 'enum C'" }
C b : 3; // { dg-bogus "'S::b' is too small to hold all values of 'enum C'" }
D c : 3; // { dg-warning "'S::c' is too small to hold all values of 'enum D'" }
D d : 4; // { dg-bogus "'S::d' is too small to hold all values of 'enum D'" }
E e : 2; // { dg-warning "'S::e' is too small to hold all values of 'enum class E'" }
E f : 3; // { dg-bogus "'S::f' is too small to hold all values of 'enum class E'" }
F g : 3; // { dg-warning "'S::g' is too small to hold all values of 'enum F'" }
F h : 4; // { dg-bogus "'S::h' is too small to hold all values of 'enum F'" }
G i : 2; // { dg-warning "'S::i' is too small to hold all values of 'enum G'" }
G j : 3; // { dg-bogus "'S::j' is too small to hold all values of 'enum G'" }
H k : 3; // { dg-warning "'S::k' is too small to hold all values of 'enum H'" }
H l : 4; // { dg-bogus "'S::l' is too small to hold all values of 'enum H'" }
};
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