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>
PR c/91985
......
......@@ -1866,6 +1866,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
typefm = make_signed_type (TYPE_PRECISION (typefm));
TREE_TYPE (typefm) = type;
}
*no_add_attrs = false;
}
else if (VECTOR_MODE_P (mode)
? 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>
* typeck.c (cp_build_indirect_ref_1): Add location_t parameter
......
......@@ -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
enclosing type. Issue any appropriate messages and set appropriate
flags. Returns false if an error has been diagnosed. */
......@@ -3326,7 +3380,7 @@ check_bitfield_decl (tree field)
"width of %qD exceeds its type", field);
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)
warning_at (DECL_SOURCE_LOCATION (field), 0,
"%qD is too small to hold all values of %q#T",
......
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
* g++.dg/opt/pr92644.C: New test.
......
......@@ -5,5 +5,5 @@ enum class MyEnum { A = 1 };
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