Skip to content

Commit 9b607d8

Browse files
authored
Merge pull request #5431 from danpoe/feature/enums-with-underlying-type
Add support for enums with underlying type specifications to the parser
2 parents b0b3225 + 75f9c49 commit 9b607d8

File tree

5 files changed

+102
-19
lines changed

5 files changed

+102
-19
lines changed

regression/ansi-c/enum9/main.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
typedef enum : unsigned
2+
{
3+
X
4+
} my_enum1;
5+
6+
enum my_enum2 : unsigned
7+
{
8+
Y
9+
};
10+
11+
struct S
12+
{
13+
enum my_enum2 : unsigned a;
14+
enum my_enum2 : unsigned b : 2;
15+
};
16+
17+
int main()
18+
{
19+
enum my_enum2 : unsigned enum_var1;
20+
}

regression/ansi-c/enum9/test.desc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--verbosity 2
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
(main.c:1:\d+)|(main.c\(1\)): warning: ignoring specification of underlying type for enum
7+
(main.c:6:\d+)|(main.c\(6\)): warning: ignoring specification of underlying type for enum
8+
(main.c:13:\d+)|(main.c\(13\)): warning: ignoring specification of underlying type for enum
9+
(main.c:14:\d+)|(main.c\(14\)): warning: ignoring specification of underlying type for enum
10+
(main.c:19:\d+)|(main.c\(19\)): warning: ignoring specification of underlying type for enum
11+
--
12+
--
13+
Checks that files containing enums with an underlying type specification can be
14+
parsed, and that a warning is output saying that the specification is ignored

src/ansi-c/c_typecheck_type.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,12 @@ void c_typecheck_baset::typecheck_c_enum_type(typet &type)
11601160
throw 0;
11611161
}
11621162

1163+
if(as_expr.find(ID_enum_underlying_type).is_not_nil())
1164+
{
1165+
warning().source_location = source_location;
1166+
warning() << "ignoring specification of underlying type for enum" << eom;
1167+
}
1168+
11631169
// enums start at zero;
11641170
// we also track min and max to find a nice base type
11651171
mp_integer value=0, min_value=0, max_value=0;
@@ -1352,6 +1358,12 @@ void c_typecheck_baset::typecheck_c_enum_tag_type(c_enum_tag_typet &type)
13521358
throw 0;
13531359
}
13541360

1361+
if(type.find(ID_enum_underlying_type).is_not_nil())
1362+
{
1363+
warning().source_location = type.source_location();
1364+
warning() << "ignoring specification of underlying type for enum" << eom;
1365+
}
1366+
13551367
source_locationt source_location=type.source_location();
13561368

13571369
irept &tag=type.add(ID_tag);

src/ansi-c/parser.y

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,14 @@ extern char *yyansi_ctext;
267267

268268
%start grammar
269269

270-
%expect 1 /* the famous "dangling `else'" ambiguity */
270+
%expect 2 /* the famous "dangling `else'" ambiguity */
271271
/* results in one shift/reduce conflict */
272272
/* that we don't want to be reported */
273273

274+
/* a second shift/reduce conflict arises due to enum underlying */
275+
/* type specifications and bitfield specifications, which are both */
276+
/* introduced by a ':' and follow a type */
277+
274278
%{
275279
/************************************************************************/
276280
/*** rules **************************************************************/
@@ -1790,23 +1794,15 @@ bit_field_size:
17901794
enum_name:
17911795
enum_key
17921796
gcc_type_attribute_opt
1793-
{
1794-
// an anon enum
1795-
}
1796-
'{' enumerator_list_opt '}'
1797-
gcc_type_attribute_opt
1797+
enum_underlying_type_opt
17981798
{
1799-
parser_stack($1).operands().swap(parser_stack($5).operands());
1800-
$$=merge($1, merge($2, $7)); // throw in the gcc attributes
1801-
}
1802-
| enum_key
1803-
gcc_type_attribute_opt
1804-
identifier_or_typedef_name
1799+
// an anon enum
1800+
if(parser_stack($3).is_not_nil())
18051801
{
1806-
// an enum with tag
1807-
parser_stack($1).set(ID_tag, parser_stack($3));
1802+
parser_stack($1).set(ID_enum_underlying_type, parser_stack($3));
18081803
}
1809-
'{' enumerator_list_opt '}'
1804+
}
1805+
'{' enumerator_list_opt '}'
18101806
gcc_type_attribute_opt
18111807
{
18121808
parser_stack($1).operands().swap(parser_stack($6).operands());
@@ -1815,14 +1811,54 @@ enum_name:
18151811
| enum_key
18161812
gcc_type_attribute_opt
18171813
identifier_or_typedef_name
1818-
gcc_type_attribute_opt
1814+
enum_underlying_type_opt
18191815
{
1820-
parser_stack($1).id(ID_c_enum_tag); // tag only
1816+
// an enum with tag
18211817
parser_stack($1).set(ID_tag, parser_stack($3));
1822-
$$=merge($1, merge($2, $4)); // throw in the gcc attributes
1818+
1819+
if(parser_stack($4).is_not_nil())
1820+
{
1821+
parser_stack($1).set(ID_enum_underlying_type, parser_stack($4));
1822+
}
1823+
}
1824+
braced_enumerator_list_opt
1825+
gcc_type_attribute_opt
1826+
{
1827+
if(parser_stack($6).is_not_nil())
1828+
{
1829+
parser_stack($1).operands().swap(parser_stack($6).operands());
1830+
}
1831+
else
1832+
{
1833+
parser_stack($1).id(ID_c_enum_tag);
1834+
}
1835+
1836+
$$=merge($1, merge($2, $7)); // throw in the gcc attributes
18231837
}
18241838
;
1825-
1839+
1840+
enum_underlying_type_opt:
1841+
/* empty */
1842+
{
1843+
init($$);
1844+
parser_stack($$).make_nil();
1845+
}
1846+
| ':' basic_type_name
1847+
{
1848+
$$=$2;
1849+
}
1850+
1851+
braced_enumerator_list_opt:
1852+
/* empty */
1853+
{
1854+
init($$);
1855+
parser_stack($$).make_nil();
1856+
}
1857+
| '{' enumerator_list_opt '}'
1858+
{
1859+
$$=$2;
1860+
}
1861+
18261862
enum_key: TOK_ENUM
18271863
{
18281864
$$=$1;

src/util/irep_ids.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ IREP_ID_ONE(NULL)
212212
IREP_ID_ONE(null)
213213
IREP_ID_ONE(nullptr)
214214
IREP_ID_ONE(c_enum)
215+
IREP_ID_ONE(enum_underlying_type)
215216
IREP_ID_ONE(enumeration)
216217
IREP_ID_ONE(elements)
217218
IREP_ID_ONE(unknown)

0 commit comments

Comments
 (0)