diff --git a/src/cc65/exprdesc.c b/src/cc65/exprdesc.c index 7d0ace004..3d7b7c384 100644 --- a/src/cc65/exprdesc.c +++ b/src/cc65/exprdesc.c @@ -93,7 +93,8 @@ int ED_IsLocPrimaryOrExpr (const ExprDesc* Expr) int ED_IsIndExpr (const ExprDesc* Expr) /* Check if the expression is a reference to its value */ { - return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr); + return (Expr->Flags & E_ADDRESS_OF) == 0 && + !ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr); } #endif @@ -281,7 +282,7 @@ ExprDesc* ED_AddrExpr (ExprDesc* Expr) case E_LOC_EXPR: Expr->Flags &= ~(E_MASK_LOC | E_MASK_RTYPE); - Expr->Flags |= E_ADDRESS_OF | E_LOC_PRIMARY | E_RTYPE_RVAL; + Expr->Flags |= E_LOC_PRIMARY | E_RTYPE_RVAL; break; default: diff --git a/src/cc65/exprdesc.h b/src/cc65/exprdesc.h index a1674a7cc..f1f121cc4 100644 --- a/src/cc65/exprdesc.h +++ b/src/cc65/exprdesc.h @@ -507,7 +507,8 @@ INLINE int ED_IsAddrExpr (const ExprDesc* Expr) INLINE int ED_IsIndExpr (const ExprDesc* Expr) /* Check if the expression is a reference to its value */ { - return (Expr->Flags & E_ADDRESS_OF) == 0 && !ED_IsLocNone (Expr); + return (Expr->Flags & E_ADDRESS_OF) == 0 && + !ED_IsLocNone (Expr) && !ED_IsLocPrimary (Expr); } #else int ED_IsIndExpr (const ExprDesc* Expr); diff --git a/src/cc65/loadexpr.c b/src/cc65/loadexpr.c index 0b75e0a9c..ccd694e35 100644 --- a/src/cc65/loadexpr.c +++ b/src/cc65/loadexpr.c @@ -92,7 +92,6 @@ static void LoadAddress (unsigned Flags, ExprDesc* Expr) g_leasp (Expr->IVal); break; - case E_LOC_PRIMARY: case E_LOC_EXPR: if (Expr->IVal != 0) { /* We have an expression in the primary plus a constant diff --git a/test/val/bug1847-struct-field-access.c b/test/val/bug1847-struct-field-access.c new file mode 100644 index 000000000..50ae32332 --- /dev/null +++ b/test/val/bug1847-struct-field-access.c @@ -0,0 +1,46 @@ +/* Bug #1847 - struct field access */ + +#include + +struct TestStruct { + char a; + char b; + char c; +}; + +struct TestStruct s0[2] = { {0xFF, 0, 0xFF}, {0, 0x42, 0xFF} }; +struct TestStruct* s0Ptr = s0; + +#define TEST_READ_SUB(X, E) \ + if ((X) != (E)) { \ + printf(#X ": 0x%X, expected: 0x%X\n", (X), (E)); \ + ++failures; \ + } + +#define TEST_READ(S, I, F, E) \ + TEST_READ_SUB(S[I].F, E) \ + TEST_READ_SUB((&S[I])->F, E) \ + TEST_READ_SUB((&S[I])[0].F, E) \ + TEST_READ_SUB(S##Ptr[I].F, E) \ + TEST_READ_SUB((&S##Ptr[I])->F, E) \ + TEST_READ_SUB((&(S##Ptr[I]))[0].F, E) \ + TEST_READ_SUB((&(*S##Ptr))[I].F, E) \ + TEST_READ_SUB((&(*S##Ptr)+I)->F, E) \ + TEST_READ_SUB((S##Ptr+I)->F, E) \ + TEST_READ_SUB((S##Ptr+I)[0].F, E) + +static unsigned failures = 0; + +int main(void) { + struct TestStruct s1[2] = { {0xFF, 0, 0xFF}, {0, 42, 0xFF} }; + struct TestStruct* s1Ptr = s1; + + TEST_READ(s0, 1, b, 0x42) + TEST_READ(s1, 1, b, 42) + + if (failures > 0) { + printf("Failures: %u\n", failures); + } + + return 0; +}