mirror of
https://github.com/cc65/cc65.git
synced 2024-11-12 22:07:16 +00:00
Fix enum bit-field ICE #1244
This previously resulted in an ICE: cc65: Check failed: (Entry->Type->C & T_MASK_SIGN) == T_SIGN_SIGNED, file 'cc65/symtab.c', line 874 This CHECK is in the code that deals with changing `int` bitfields to `unsigned int`. Work around this by treating enum bit-fields as having their signedness specified, so this type change code does not get called. Fixes #1244.
This commit is contained in:
parent
1e7a9e44af
commit
9a0e4a35e1
@ -1446,6 +1446,12 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers,
|
||||
D->Type[0].C |= T_ENUM;
|
||||
SetESUSymEntry (D->Type, Entry);
|
||||
D->Type[1].C = T_END;
|
||||
/* The signedness of enums is determined by the type, so say this is specified to avoid
|
||||
** the int -> unsigned int handling for plain int bit-fields in AddBitField.
|
||||
*/
|
||||
if (SignednessSpecified) {
|
||||
*SignednessSpecified = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TOK_IDENT:
|
||||
|
@ -870,6 +870,7 @@ SymEntry* AddBitField (const char* Name, const Type* T, unsigned Offs,
|
||||
if (!SignednessSpecified) {
|
||||
/* int is treated as signed int everywhere except bit-fields; switch it to unsigned,
|
||||
** since this is allowed for bit-fields and avoids sign-extension, so is much faster.
|
||||
** enums set SignednessSpecified to 1 to avoid this adjustment.
|
||||
*/
|
||||
CHECK ((Entry->Type->C & T_MASK_SIGN) == T_SIGN_SIGNED);
|
||||
Entry->Type->C &= ~T_MASK_SIGN;
|
||||
|
158
test/val/enum-bitfield.c
Normal file
158
test/val/enum-bitfield.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
Copyright 2020 The cc65 Authors
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
Tests of enum bit-fields; see https://github.com/cc65/cc65/issues/1244
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static unsigned char failures = 0;
|
||||
|
||||
/* Enum with underlying type unsigned int. */
|
||||
enum e10u {
|
||||
E10U_200 = 200,
|
||||
E10U_1000 = 1000,
|
||||
};
|
||||
|
||||
static struct enum_bitfield_uint {
|
||||
enum e10u x : 1;
|
||||
enum e10u y : 8;
|
||||
enum e10u z : 16;
|
||||
} e10ubf = {0, E10U_200, E10U_1000};
|
||||
|
||||
static void test_enum_bitfield_uint(void)
|
||||
{
|
||||
if (sizeof (struct enum_bitfield_uint) != 4) {
|
||||
printf ("Got sizeof(struct enum_bitfield_uint) = %zu, expected 4.\n",
|
||||
sizeof(struct enum_bitfield_uint));
|
||||
failures++;
|
||||
}
|
||||
|
||||
if (e10ubf.x != 0) {
|
||||
printf ("Got e10ubf.x = %u, expected 0.\n", e10ubf.x);
|
||||
failures++;
|
||||
}
|
||||
if (e10ubf.y != 200) {
|
||||
printf ("Got e10ubf.y = %u, expected 200.\n", e10ubf.y);
|
||||
failures++;
|
||||
}
|
||||
if (e10ubf.z != 1000) {
|
||||
printf ("Got e10ubf.z = %u, expected 1000.\n", e10ubf.z);
|
||||
failures++;
|
||||
}
|
||||
|
||||
e10ubf.x = 1;
|
||||
e10ubf.y = 17;
|
||||
e10ubf.z = 1023;
|
||||
|
||||
if (e10ubf.x != 1) {
|
||||
printf ("Got e10ubf.x = %u, expected 1.\n", e10ubf.x);
|
||||
failures++;
|
||||
}
|
||||
|
||||
/* Check signedness, should be unsigned. */
|
||||
{
|
||||
long v = e10ubf.x - 2;
|
||||
if (v < 0) {
|
||||
printf ("Got negative v = %ld, expected large positive.\n", v);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
|
||||
if (e10ubf.y != 17) {
|
||||
printf ("Got e10ubf.y = %u, expected 17.\n", e10ubf.y);
|
||||
failures++;
|
||||
}
|
||||
if (e10ubf.z != 1023) {
|
||||
printf ("Got e10ubf.z = %u, expected 1023.\n", e10ubf.z);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enum with underlying type signed int. */
|
||||
enum e11i {
|
||||
E11I_M1 = -1,
|
||||
E11I_100 = 100,
|
||||
E11I_1000 = 1000,
|
||||
};
|
||||
|
||||
static struct enum_bitfield_int {
|
||||
enum e11i x : 2;
|
||||
enum e11i y : 8;
|
||||
enum e11i z : 16;
|
||||
} e11ibf = {E11I_M1, E11I_100, E11I_1000};
|
||||
|
||||
static void test_enum_bitfield_int(void)
|
||||
{
|
||||
if (sizeof (struct enum_bitfield_int) != 4) {
|
||||
printf ("Got sizeof(struct enum_bitfield_int) = %zu, expected 4.\n",
|
||||
sizeof(struct enum_bitfield_int));
|
||||
failures++;
|
||||
}
|
||||
|
||||
if (e11ibf.x != -1) {
|
||||
printf ("Got e11ibf.x = %d, expected -1.\n", e11ibf.x);
|
||||
failures++;
|
||||
}
|
||||
if (e11ibf.y != 100) {
|
||||
printf ("Got e11ibf.y = %d, expected 100.\n", e11ibf.y);
|
||||
failures++;
|
||||
}
|
||||
if (e11ibf.z != 1000) {
|
||||
printf ("Got e11ibf.z = %d, expected 1000.\n", e11ibf.z);
|
||||
failures++;
|
||||
}
|
||||
|
||||
e11ibf.x = 1;
|
||||
e11ibf.y = 17;
|
||||
e11ibf.z = 1023;
|
||||
|
||||
if (e11ibf.x != 1) {
|
||||
printf ("Got e11ibf.x = %d, expected 1.\n", e11ibf.x);
|
||||
failures++;
|
||||
}
|
||||
|
||||
/* Check signedness, should be signed. */
|
||||
{
|
||||
long v = e11ibf.x - 2;
|
||||
if (v > 0) {
|
||||
printf ("Got positive v = %ld, expected negative.\n", v);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
|
||||
if (e11ibf.y != 17) {
|
||||
printf ("Got e11ibf.y = %d, expected 17.\n", e11ibf.y);
|
||||
failures++;
|
||||
}
|
||||
if (e11ibf.z != 1023) {
|
||||
printf ("Got e11ibf.z = %d, expected 1023.\n", e11ibf.z);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_enum_bitfield_uint();
|
||||
test_enum_bitfield_int();
|
||||
printf("failures: %u\n", failures);
|
||||
return failures;
|
||||
}
|
Loading…
Reference in New Issue
Block a user