diff --git a/src/cc65/typecmp.c b/src/cc65/typecmp.c index 29c8fe51e..1a108159f 100644 --- a/src/cc65/typecmp.c +++ b/src/cc65/typecmp.c @@ -266,18 +266,6 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) LeftType = (GetUnderlyingTypeCode (lhs) & T_MASK_TYPE); RightType = (GetUnderlyingTypeCode (rhs) & T_MASK_TYPE); - /* If one side is a pointer and the other side is an array, both are - ** compatible. - */ - if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { - RightType = T_TYPE_PTR; - SetResult (Result, TC_PTR_DECAY); - } - if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) { - LeftType = T_TYPE_PTR; - SetResult (Result, TC_STRICT_COMPATIBLE); - } - /* Bit-fields are considered compatible if they have the same ** signedness, bit-offset and bit-width. */ @@ -287,12 +275,27 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result) lhs->A.B.Offs != rhs->A.B.Offs || lhs->A.B.Width != rhs->A.B.Width) { SetResult (Result, TC_INCOMPATIBLE); + return; } if (LeftType != RightType) { SetResult (Result, TC_STRICT_COMPATIBLE); } } + /* If one side is a pointer and the other side is an array, both are + ** compatible. + */ + if (Result->Indirections == 0) { + if (LeftType == T_TYPE_PTR && RightType == T_TYPE_ARRAY) { + RightType = T_TYPE_PTR; + SetResult (Result, TC_PTR_DECAY); + } + if (LeftType == T_TYPE_ARRAY && RightType == T_TYPE_PTR) { + LeftType = T_TYPE_PTR; + SetResult (Result, TC_STRICT_COMPATIBLE); + } + } + /* If the underlying types are not identical, the types are incompatible */ if (LeftType != RightType) { SetResult (Result, TC_INCOMPATIBLE); diff --git a/test/err/bug1895-assign1a.c b/test/err/bug1895-assign1a.c new file mode 100644 index 000000000..223964104 --- /dev/null +++ b/test/err/bug1895-assign1a.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_1_A + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign1b.c b/test/err/bug1895-assign1b.c new file mode 100644 index 000000000..cccc0a318 --- /dev/null +++ b/test/err/bug1895-assign1b.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_1_B + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign2a.c b/test/err/bug1895-assign2a.c new file mode 100644 index 000000000..512b658a9 --- /dev/null +++ b/test/err/bug1895-assign2a.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_2_A + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign2b.c b/test/err/bug1895-assign2b.c new file mode 100644 index 000000000..d07191206 --- /dev/null +++ b/test/err/bug1895-assign2b.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_2_B + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign4a.c b/test/err/bug1895-assign4a.c new file mode 100644 index 000000000..c2a6f25de --- /dev/null +++ b/test/err/bug1895-assign4a.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_4_A + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign4b.c b/test/err/bug1895-assign4b.c new file mode 100644 index 000000000..740e10b04 --- /dev/null +++ b/test/err/bug1895-assign4b.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_4_B + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign5a.c b/test/err/bug1895-assign5a.c new file mode 100644 index 000000000..fed4e07d9 --- /dev/null +++ b/test/err/bug1895-assign5a.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_5_A + +#include "bug1895-common.h" diff --git a/test/err/bug1895-assign5b.c b/test/err/bug1895-assign5b.c new file mode 100644 index 000000000..ed8498e34 --- /dev/null +++ b/test/err/bug1895-assign5b.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_1_SUB_5_B + +#include "bug1895-common.h" diff --git a/test/err/bug1895-common.h b/test/err/bug1895-common.h new file mode 100644 index 000000000..03f02e2de --- /dev/null +++ b/test/err/bug1895-common.h @@ -0,0 +1,196 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types + + Test of incompatible pointer/array types in assignment ans conditional + expressions, as well as function prototypes. + + In each source file, define a single macro and include this file to perform + a coresponding test individually. + + https://github.com/cc65/cc65/issues/1895 +*/ + +/* Test 1 suite */ +#ifdef DO_TEST_1_SUB_1_A +#define TEST_1_SUB_1_A CMP_TYPES_1 +#else +#define TEST_1_SUB_1_A BLANK +#endif + +#ifdef DO_TEST_1_SUB_1_B +#define TEST_1_SUB_1_B CMP_TYPES_1 +#else +#define TEST_1_SUB_1_B BLANK +#endif + +#ifdef DO_TEST_1_SUB_2_A +#define TEST_1_SUB_2_A CMP_TYPES_1 +#else +#define TEST_1_SUB_2_A BLANK +#endif + +#ifdef DO_TEST_1_SUB_2_B +#define TEST_1_SUB_2_B CMP_TYPES_1 +#else +#define TEST_1_SUB_2_B BLANK +#endif + +#ifdef DO_TEST_1_SUB_4_A +#define TEST_1_SUB_4_A CMP_TYPES_1 +#else +#define TEST_1_SUB_4_A BLANK +#endif + +#ifdef DO_TEST_1_SUB_4_B +#define TEST_1_SUB_4_B CMP_TYPES_1 +#else +#define TEST_1_SUB_4_B BLANK +#endif + +#ifdef DO_TEST_1_SUB_5_A +#define TEST_1_SUB_5_A CMP_TYPES_1 +#else +#define TEST_1_SUB_5_A BLANK +#endif + +#ifdef DO_TEST_1_SUB_5_B +#define TEST_1_SUB_5_B CMP_TYPES_1 +#else +#define TEST_1_SUB_5_B BLANK +#endif + +/* Test 2 suite */ +#ifdef DO_TEST_2_SUB_1 +#define TEST_2_SUB_1 CMP_TYPES_2 +#else +#define TEST_2_SUB_1 BLANK +#endif + +#ifdef DO_TEST_2_SUB_2 +#define TEST_2_SUB_2 CMP_TYPES_2 +#else +#define TEST_2_SUB_2 BLANK +#endif + +#ifdef DO_TEST_2_SUB_3 +#define TEST_2_SUB_3 CMP_TYPES_2 +#else +#define TEST_2_SUB_3 BLANK +#endif + +#ifdef DO_TEST_2_SUB_4 +#define TEST_2_SUB_4 CMP_TYPES_2 +#else +#define TEST_2_SUB_4 BLANK +#endif + +#ifdef DO_TEST_2_SUB_5 +#define TEST_2_SUB_5 CMP_TYPES_2 +#else +#define TEST_2_SUB_5 BLANK +#endif + +/* Test 3 suite */ +#ifdef DO_TEST_3_SUB_1 +#define TEST_3_SUB_1 CMP_TYPES_3 +#else +#define TEST_3_SUB_1 BLANK +#endif + +#ifdef DO_TEST_3_SUB_2 +#define TEST_3_SUB_2 CMP_TYPES_3 +#else +#define TEST_3_SUB_2 BLANK +#endif + +#ifdef DO_TEST_3_SUB_3 +#define TEST_3_SUB_3 CMP_TYPES_3 +#else +#define TEST_3_SUB_3 BLANK +#endif + +#ifdef DO_TEST_3_SUB_4 +#define TEST_3_SUB_4 CMP_TYPES_3 +#else +#define TEST_3_SUB_4 BLANK +#endif + +#ifdef DO_TEST_3_SUB_5 +#define TEST_3_SUB_5 CMP_TYPES_3 +#else +#define TEST_3_SUB_5 BLANK +#endif + +/* Implementation */ +#define CONCAT(a, b) CONCAT_impl_(a, b) +#define CONCAT_impl_(a, b) a##b +#define BLANK(...) +#define DECL_FUNCS(A, B)\ + void CONCAT(foo_,__LINE__)(A); void CONCAT(foo_,__LINE__)(B); + +/* Test with assignment */ +#define CMP_TYPES_1(A, B)\ + do {\ + A p; B q;\ +_Pragma("warn(error, on)")\ + p = q;\ +_Pragma("warn(error, off)")\ + } while (0) + +/* Test with conditional expression */ +#define CMP_TYPES_2(A, B)\ + do {\ + A p; B q;\ +_Pragma("warn(error, on)")\ + v = v ? p : q;\ +_Pragma("warn(error, off)")\ + } while (0) + +/* Test with function prototype */ +#define CMP_TYPES_3(A, B)\ + do {\ + DECL_FUNCS(A,B);\ + } while (0) + +static void *v; + +typedef int (*p1)[3]; /* pointer to array */ +typedef int **q1; /* pointer to pointer */ +typedef int (**p2)[3]; /* pointer to pointer to array */ +typedef int ***q2; /* pointer to pointer to pointer */ +typedef int p3[1][3]; /* array of array */ +typedef int *q3[1]; /* array of pointer */ +typedef int const **p4; /* pointer to pointer to const */ +typedef int **q4; /* pointer to pointer to non-const */ +typedef int (*p5)(int (*)(p3)); /* pointer to function taking pointer to function taking pointer to array */ +typedef int (*q5)(int (*)(q3)); /* pointer to function taking pointer to function taking pointer to pointer */ + +int main(void) +{ + /* Warnings */ + TEST_1_SUB_1_A(p1, q1); + TEST_1_SUB_1_B(q1, p1); + TEST_1_SUB_2_A(p2, q2); + TEST_1_SUB_2_B(q2, p2); + /* TEST_1_SUB_3_A(p3, q3); */ + /* TEST_1_SUB_3_B(q3, p3); */ + TEST_1_SUB_4_A(p4, q4); + TEST_1_SUB_4_B(q4, p4); + TEST_1_SUB_5_A(p5, q5); + TEST_1_SUB_5_B(q5, p5); + + /* GCC and clang give warnings while cc65 gives errors */ + TEST_2_SUB_1(p1, q1); + TEST_2_SUB_2(p2, q2); + TEST_2_SUB_3(p3, q3); + TEST_2_SUB_4(p4, q4); + TEST_2_SUB_5(p5, q5); + + /* Errors */ + TEST_3_SUB_1(p1, q1); + TEST_3_SUB_2(p2, q2); + TEST_3_SUB_3(p3, q3); + TEST_3_SUB_4(p4, q4); + TEST_3_SUB_5(p5, q5); + + return 0; +} diff --git a/test/err/bug1895-cond1.c b/test/err/bug1895-cond1.c new file mode 100644 index 000000000..ac6a301c9 --- /dev/null +++ b/test/err/bug1895-cond1.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_1 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-cond2.c b/test/err/bug1895-cond2.c new file mode 100644 index 000000000..81b8b2912 --- /dev/null +++ b/test/err/bug1895-cond2.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_2 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-cond3.c b/test/err/bug1895-cond3.c new file mode 100644 index 000000000..f1571acbf --- /dev/null +++ b/test/err/bug1895-cond3.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_3 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-cond4.c b/test/err/bug1895-cond4.c new file mode 100644 index 000000000..e7ef77964 --- /dev/null +++ b/test/err/bug1895-cond4.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_4 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-cond5.c b/test/err/bug1895-cond5.c new file mode 100644 index 000000000..1625c599b --- /dev/null +++ b/test/err/bug1895-cond5.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_2_SUB_5 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype1.c b/test/err/bug1895-prototype1.c new file mode 100644 index 000000000..30331e757 --- /dev/null +++ b/test/err/bug1895-prototype1.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_1 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype2.c b/test/err/bug1895-prototype2.c new file mode 100644 index 000000000..c8fe213f4 --- /dev/null +++ b/test/err/bug1895-prototype2.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_2 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype3.c b/test/err/bug1895-prototype3.c new file mode 100644 index 000000000..f7d2b79e4 --- /dev/null +++ b/test/err/bug1895-prototype3.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_3 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype4.c b/test/err/bug1895-prototype4.c new file mode 100644 index 000000000..3d0fe2c05 --- /dev/null +++ b/test/err/bug1895-prototype4.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_4 + +#include "bug1895-common.h" diff --git a/test/err/bug1895-prototype5.c b/test/err/bug1895-prototype5.c new file mode 100644 index 000000000..ba9b997c9 --- /dev/null +++ b/test/err/bug1895-prototype5.c @@ -0,0 +1,5 @@ +/* Bug #1895 - missing diagnostics on incompatible pointer/array types */ + +#define DO_TEST_3_SUB_5 + +#include "bug1895-common.h"