mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +00:00
Merge pull request #2072 from bbbradsmith/struct-passing
Forbid 3-byte struct pass/return by value, document struct value pass/return
This commit is contained in:
commit
7d9a736b7f
@ -741,7 +741,7 @@ Here is a description of all the command line options:
|
|||||||
<tag><tt/return-type/</tag>
|
<tag><tt/return-type/</tag>
|
||||||
Warn about no return statement in function returning non-void.
|
Warn about no return statement in function returning non-void.
|
||||||
<tag><tt/struct-param/</tag>
|
<tag><tt/struct-param/</tag>
|
||||||
Warn when passing structs by value.
|
Warn when passing structs by value. (Disabled by default.)
|
||||||
<tag><tt/unknown-pragma/</tag>
|
<tag><tt/unknown-pragma/</tag>
|
||||||
Warn about #pragmas that aren't recognized by cc65.
|
Warn about #pragmas that aren't recognized by cc65.
|
||||||
<tag><tt/unreachable-code/</tag>
|
<tag><tt/unreachable-code/</tag>
|
||||||
@ -806,9 +806,8 @@ and the one defined by the ISO standard:
|
|||||||
|
|
||||||
<item> The datatypes "float" and "double" are not available.
|
<item> The datatypes "float" and "double" are not available.
|
||||||
<p>
|
<p>
|
||||||
<item> C Functions may not return structs (or unions), and structs may not
|
<item> C Functions may pass and return structs (or unions) by value, but only
|
||||||
be passed as parameters by value. However, struct assignment *is*
|
of 1, 2 or 4 byte sizes.
|
||||||
possible.
|
|
||||||
<p>
|
<p>
|
||||||
<item> Most of the C library is available with only the fastcall calling
|
<item> Most of the C library is available with only the fastcall calling
|
||||||
convention (<ref id="extension-fastcall" name="see below">). It means
|
convention (<ref id="extension-fastcall" name="see below">). It means
|
||||||
|
@ -803,7 +803,6 @@ const Type* GetStructReplacementType (const Type* SType)
|
|||||||
switch (SizeOf (SType)) {
|
switch (SizeOf (SType)) {
|
||||||
case 1: NewType = type_uchar; break;
|
case 1: NewType = type_uchar; break;
|
||||||
case 2: NewType = type_uint; break;
|
case 2: NewType = type_uint; break;
|
||||||
case 3: /* FALLTHROUGH */
|
|
||||||
case 4: NewType = type_ulong; break;
|
case 4: NewType = type_ulong; break;
|
||||||
default: NewType = SType; break;
|
default: NewType = SType; break;
|
||||||
}
|
}
|
||||||
|
144
test/val/struct-by-value.c
Normal file
144
test/val/struct-by-value.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/* Test of passing and returning structs by value.
|
||||||
|
Structs of 1, 2 and 4 bytes are supported.
|
||||||
|
Note that structs of 3 bytes are disabled, see:
|
||||||
|
https://github.com/cc65/cc65/issues/2022
|
||||||
|
*/
|
||||||
|
|
||||||
|
int fail = 0;
|
||||||
|
|
||||||
|
struct s1 { char a; };
|
||||||
|
struct s2 { char a, b; };
|
||||||
|
struct s3 { char a, b, c; };
|
||||||
|
struct s4 { char a, b, c, d; };
|
||||||
|
|
||||||
|
const struct s1 c1 = { 1 };
|
||||||
|
const struct s2 c2 = { 2, 3 };
|
||||||
|
const struct s3 c3 = { 4, 5, 6 };
|
||||||
|
const struct s4 c4 = { 7, 8, 9, 10 };
|
||||||
|
|
||||||
|
struct s1 return1() { return c1; }
|
||||||
|
struct s2 return2() { return c2; }
|
||||||
|
/*struct s3 return3() { return c3; }*/
|
||||||
|
struct s4 return4() { return c4; }
|
||||||
|
|
||||||
|
int compare1(struct s1 a, struct s1 b)
|
||||||
|
{
|
||||||
|
if (a.a != b.a) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare2(struct s2 a, struct s2 b)
|
||||||
|
{
|
||||||
|
if (a.a != b.a) return 1;
|
||||||
|
if (a.b != b.b) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*int compare3(struct s3 a, struct s3 b)
|
||||||
|
{
|
||||||
|
if (a.a != b.a) return 1;
|
||||||
|
if (a.b != b.b) return 1;
|
||||||
|
if (a.c != b.c) return 1;
|
||||||
|
return 0;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
int compare4(struct s4 a, struct s4 b)
|
||||||
|
{
|
||||||
|
if (a.a != b.a) return 1;
|
||||||
|
if (a.b != b.b) return 1;
|
||||||
|
if (a.c != b.c) return 1;
|
||||||
|
if (a.d != b.d) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pass1(struct s1 p1)
|
||||||
|
{
|
||||||
|
struct s1 a1;
|
||||||
|
a1 = p1;
|
||||||
|
if (a1.a != c1.a) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pass2(struct s2 p2)
|
||||||
|
{
|
||||||
|
struct s2 a2;
|
||||||
|
a2 = p2;
|
||||||
|
if (a2.a != c2.a) return 1;
|
||||||
|
if (a2.b != c2.b) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*int pass3(struct s3 p3)
|
||||||
|
{
|
||||||
|
struct s3 a3;
|
||||||
|
a3 = p3;
|
||||||
|
if (a3.a != c3.a) return 1;
|
||||||
|
if (a3.b != c3.b) return 1;
|
||||||
|
if (a3.c != c3.c) return 1;
|
||||||
|
return 0;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
int pass4(struct s4 p4)
|
||||||
|
{
|
||||||
|
struct s4 a4;
|
||||||
|
a4 = p4;
|
||||||
|
if (a4.a != c4.a) return 1;
|
||||||
|
if (a4.b != c4.b) return 1;
|
||||||
|
if (a4.c != c4.c) return 1;
|
||||||
|
if (a4.d != c4.d) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(char* gg)
|
||||||
|
{
|
||||||
|
char i;
|
||||||
|
for (i=0;i<5;++i) gg[i] = 128+i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int test(char* gg, char start)
|
||||||
|
{
|
||||||
|
char i;
|
||||||
|
for (i=start;i<5;++i)
|
||||||
|
if (gg[i] != 128+i) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
/* Used to check #2022 bug condition of extra bytes being overwritten. */
|
||||||
|
union
|
||||||
|
{
|
||||||
|
char gg[5];
|
||||||
|
struct s1 g1;
|
||||||
|
struct s2 g2;
|
||||||
|
struct s3 g3;
|
||||||
|
struct s4 g4;
|
||||||
|
} guard;
|
||||||
|
|
||||||
|
reset(guard.gg);
|
||||||
|
guard.g1 = return1();
|
||||||
|
fail += compare1(guard.g1,c1);
|
||||||
|
fail += test(guard.gg,1);
|
||||||
|
|
||||||
|
reset(guard.gg);
|
||||||
|
guard.g2 = return2();
|
||||||
|
fail += compare2(guard.g2,c2);
|
||||||
|
fail += test(guard.gg,2);
|
||||||
|
|
||||||
|
/*reset(guard.gg);
|
||||||
|
guard.g3 = return3();
|
||||||
|
fail += compare3(guard.g3,c3);
|
||||||
|
fail += test(guard.gg,3);*/
|
||||||
|
|
||||||
|
reset(guard.gg);
|
||||||
|
guard.g4 = return4();
|
||||||
|
fail += compare4(guard.g4,c4);
|
||||||
|
fail += test(guard.gg,4);
|
||||||
|
|
||||||
|
fail += pass1(c1);
|
||||||
|
fail += pass2(c2);
|
||||||
|
/*fail += pass3(c3);*/
|
||||||
|
fail += pass4(c4);
|
||||||
|
|
||||||
|
return fail;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user