aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorMartin Uecker <uecker@tugraz.at>2024-05-18 22:00:04 +0200
committerMartin Uecker <uecker@tugraz.at>2024-06-18 12:51:01 +0200
commitc9b96a68860bfdee49d40b4a844af7c5ef69cd12 (patch)
treef60834a1db4b63494ff04765c7f9ae2735e0e8df /gcc/c
parente17114f99c9ea754787573679b3b4d2b52434b61 (diff)
downloadgcc-c9b96a68860bfdee49d40b4a844af7c5ef69cd12.zip
gcc-c9b96a68860bfdee49d40b4a844af7c5ef69cd12.tar.gz
gcc-c9b96a68860bfdee49d40b4a844af7c5ef69cd12.tar.bz2
c23: Fix for redeclared enumerator initialized with different type [PR115109]
c23 specifies that the type of a redeclared enumerator is the one of the previous declaration. Convert initializers with different type accordingly and emit an error when the value does not fit. 2024-06-01 Martin Uecker <uecker@tugraz.at> PR c/115109 gcc/c/ * c-decl.cc (build_enumerator): When redeclaring an enumerator convert value to previous type. For redeclared enumerators use underlying type for computing the next value. gcc/testsuite/ * gcc.dg/pr115109.c: New test. * gcc.dg/c23-tag-enum-6.c: New test. * gcc.dg/c23-tag-enum-7.c: New test.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/c-decl.cc29
1 files changed, 26 insertions, 3 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 6c09eb7..0132657 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -10277,6 +10277,7 @@ build_enumerator (location_t decl_loc, location_t loc,
struct c_enum_contents *the_enum, tree name, tree value)
{
tree decl;
+ tree old_decl;
/* Validate and default VALUE. */
@@ -10336,6 +10337,23 @@ build_enumerator (location_t decl_loc, location_t loc,
definition. */
value = convert (the_enum->enum_type, value);
}
+ else if (flag_isoc23
+ && (old_decl = lookup_name_in_scope (name, current_scope))
+ && old_decl != error_mark_node
+ && TREE_TYPE (old_decl)
+ && TREE_TYPE (TREE_TYPE (old_decl))
+ && TREE_CODE (old_decl) == CONST_DECL)
+ {
+ /* Enumeration constants in a redeclaration have the previous type. */
+ tree previous_type = TREE_TYPE (DECL_INITIAL (old_decl));
+ if (!int_fits_type_p (value, previous_type))
+ {
+ error_at (loc, "value of redeclared enumerator outside the range "
+ "of %qT", previous_type);
+ locate_old_decl (old_decl);
+ }
+ value = convert (previous_type, value);
+ }
else
{
/* Even though the underlying type of an enum is unspecified, the
@@ -10402,9 +10420,14 @@ build_enumerator (location_t decl_loc, location_t loc,
false);
}
else
- the_enum->enum_next_value
- = build_binary_op (EXPR_LOC_OR_LOC (value, input_location),
- PLUS_EXPR, value, integer_one_node, false);
+ {
+ /* In a redeclaration the type can already be the enumeral type. */
+ if (TREE_CODE (TREE_TYPE (value)) == ENUMERAL_TYPE)
+ value = convert (ENUM_UNDERLYING_TYPE (TREE_TYPE (value)), value);
+ the_enum->enum_next_value
+ = build_binary_op (EXPR_LOC_OR_LOC (value, input_location),
+ PLUS_EXPR, value, integer_one_node, false);
+ }
the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value);
if (the_enum->enum_overflow
&& !ENUM_FIXED_UNDERLYING_TYPE_P (the_enum->enum_type))