Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Made a C union declaration know the sizes of anonymous struct/union m…
…embers when it determines its size. The bug was located, and the fix was written, by Francesco.
- Loading branch information
1 parent
4e137cf
commit 362b6af
Showing
3 changed files
with
268 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/* | ||
!!DESCRIPTION!! Make sure that structs/unions know the sizes of anonymous struct/union members | ||
!!ORIGIN!! cc65 regression tests | ||
!!LICENCE!! Public Domain | ||
!!AUTHOR!! Greg King | ||
*/ | ||
|
||
/* | ||
see https://github.com/cc65/cc65/issues/641 | ||
*/ | ||
|
||
#include <stdio.h> | ||
|
||
static unsigned char fails = 0; | ||
|
||
typedef struct { | ||
short s1; | ||
struct { | ||
int i1; | ||
long l1; | ||
char c1; | ||
}; | ||
char c2; | ||
} s1_t; | ||
|
||
typedef struct { | ||
short s1; | ||
union { | ||
int i1; | ||
long l1; | ||
char c1; | ||
}; | ||
char c2; | ||
} s2_t; | ||
|
||
typedef union { | ||
short s1; | ||
struct { | ||
int i1; | ||
long l1; | ||
char c1; | ||
}; | ||
char c2; | ||
} u1_t; | ||
|
||
typedef union { | ||
short s1; | ||
union { | ||
int i1; | ||
long l1; | ||
char c1; | ||
}; | ||
char c2; | ||
} u2_t; | ||
|
||
static s1_t s1; | ||
static s2_t s2; | ||
static u1_t u1; | ||
static u2_t u2; | ||
|
||
/* We use "variables" in the comparisons, so that we can avoid "constant | ||
** comparison" and "Unreachable code" warnings (the second one currently | ||
** can't be suppressed). | ||
*/ | ||
|
||
static size_t const four = 4; | ||
static size_t const seven = 7; | ||
static size_t const ten = 10; | ||
|
||
int main(void) | ||
{ | ||
/* Check the types' sizes. */ | ||
|
||
if (sizeof (s1_t) != ten) { | ||
printf("s1_t size is %u; it should be 10.\n", sizeof (s1_t)); | ||
++fails; | ||
} | ||
if (sizeof (s2_t) != seven) { | ||
printf("s2_t size is %u; it should be 7.\n", sizeof (s2_t)); | ||
++fails; | ||
} | ||
if (sizeof (u1_t) != seven) { | ||
printf("u1_t size is %u; it should be 7.\n", sizeof (u1_t)); | ||
++fails; | ||
} | ||
if (sizeof (u2_t) != four) { | ||
printf("u2_t size is %u; it should be 4.\n", sizeof (u2_t)); | ||
++fails; | ||
} | ||
|
||
/* Check the variables' sizes. */ | ||
|
||
if (sizeof s1 != ten) { | ||
printf("s1 size is %u; it should be 10.\n", sizeof s1); | ||
++fails; | ||
} | ||
if (sizeof s2 != seven) { | ||
printf("s2 size is %u; it should be 7.\n", sizeof s2); | ||
++fails; | ||
} | ||
if (sizeof u1 != seven) { | ||
printf("u1 size is %u; it should be 7.\n", sizeof u1); | ||
++fails; | ||
} | ||
if (sizeof u2 != four) { | ||
printf("u2 size is %u; it should be 4.\n", sizeof u2); | ||
++fails; | ||
} | ||
|
||
return fails; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/* | ||
!!DESCRIPTION!! Make sure that the fields of anonymous structs/unions can be reached properly. | ||
!!ORIGIN!! cc65 regression tests | ||
!!LICENCE!! Public Domain | ||
!!AUTHOR!! Greg King | ||
*/ | ||
|
||
#include <stddef.h> | ||
#include <stdio.h> | ||
|
||
static unsigned char fails = 0; | ||
|
||
typedef struct { | ||
short s1; | ||
struct { | ||
char c1; | ||
int i1; | ||
long l1; | ||
}; | ||
char c2; | ||
} s1_t; | ||
|
||
typedef struct { | ||
char c2; | ||
union { | ||
int i1; | ||
char c1; | ||
long l1; | ||
}; | ||
short s1; | ||
} s2_t; | ||
|
||
typedef union { | ||
short s1; | ||
struct { | ||
int i1; | ||
long l1; | ||
char c1; | ||
}; | ||
char c2; | ||
} u1_t; | ||
|
||
typedef union { | ||
short s1; | ||
union { | ||
long l1; | ||
char c1; | ||
int i1; | ||
}; | ||
char c2; | ||
} u2_t; | ||
|
||
typedef struct { | ||
union { | ||
short s1; | ||
struct { | ||
int i1; | ||
long l1; | ||
char c1; | ||
}; | ||
char c2; | ||
}; | ||
short s2; | ||
} s3_t; | ||
|
||
static s1_t s1; | ||
static s2_t s2; | ||
static u1_t u1; | ||
static u2_t u2; | ||
|
||
static long l2; | ||
static int i2; | ||
|
||
/* We use "variables" in the comparisons, so that we can avoid "constant | ||
** comparison" and "Unreachable code" warnings (the second one currently | ||
** can't be suppressed). | ||
*/ | ||
|
||
static size_t const zero = 0; | ||
static size_t const one = 1; | ||
static size_t const three = 3; | ||
static size_t const five = 5; | ||
static size_t const six = 6; | ||
static size_t const seven = 7; | ||
static size_t const nine = 9; | ||
|
||
int main(void) | ||
{ | ||
/* Can cc65 see the names of members of anonymous structs/unions? */ | ||
|
||
l2 = s1.l1; | ||
l2 = s2.l1; | ||
l2 = u1.l1; | ||
l2 = u2.l1; | ||
|
||
i2 = s1.c1; | ||
i2 = s1.c2; | ||
i2 = s2.c1; | ||
i2 = s2.c2; | ||
i2 = u1.c1; | ||
i2 = u1.c2; | ||
i2 = u2.c1; | ||
i2 = u2.c2; | ||
|
||
/* Does cc65 use the correct offsets of | ||
** the members of anonymous structs/unions? | ||
*/ | ||
|
||
if (offsetof(s1_t, i1) != three) { | ||
printf("The offset of s1.i1 is %u; it should be 3.\n", offsetof(s1_t, i1)); | ||
++fails; | ||
} | ||
if (offsetof(s2_t, l1) != one) { | ||
printf("The offset of s2.l1 is %u; it should be 1.\n", offsetof(s2_t, l1)); | ||
++fails; | ||
} | ||
if (offsetof(u1_t, c1) != six) { | ||
printf("The offset of u1.c1 is %u; it should be 6.\n", offsetof(u1_t, c1)); | ||
++fails; | ||
} | ||
if (offsetof(u2_t, i1) != zero) { | ||
printf("The offset of u2.i1 is %u; it should be 0.\n", offsetof(u2_t, i1)); | ||
++fails; | ||
} | ||
|
||
/* Does cc65 use the correct offset of a member | ||
** that's later than an anonymous struct/union? | ||
*/ | ||
|
||
if (offsetof(s1_t, c2) != nine) { | ||
printf("The offset of s1.c2 is %u; it should be 9.\n", offsetof(s1_t, c2)); | ||
++fails; | ||
} | ||
if (offsetof(s2_t, s1) != five) { | ||
printf("The offset of s2.s1 is %u; it should be 5.\n", offsetof(s2_t, s1)); | ||
++fails; | ||
} | ||
if (offsetof(u1_t, c2) != zero) { | ||
printf("The offset of u1.c2 is %u; it should be 0.\n", offsetof(u1_t, c2)); | ||
++fails; | ||
} | ||
if (offsetof(u2_t, c2) != zero) { | ||
printf("The offset of u2.c2 is %u; it should be 0.\n", offsetof(u2_t, c2)); | ||
++fails; | ||
} | ||
if (offsetof(s3_t, s2) != seven) { | ||
printf("The offset of s3.s2 is %u; it should be 7.\n", offsetof(s3_t, s2)); | ||
++fails; | ||
} | ||
|
||
return fails; | ||
} |