1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-23 04:30:10 +00:00

Fixed local struct field access via the address of the struct.

This commit is contained in:
acqn 2021-04-05 16:40:32 +08:00 committed by Oliver Schmidt
parent f5365c7ffd
commit bd8eae67f1

View File

@ -1340,7 +1340,6 @@ static void Primary (ExprDesc* E)
static void StructRef (ExprDesc* Expr)
/* Process struct/union field after . or ->. */
{
ident Ident;
Type* FinalType;
TypeCode Q;
@ -1354,42 +1353,42 @@ static void StructRef (ExprDesc* Expr)
}
/* Get the symbol table entry and check for a struct/union field */
strcpy (Ident, CurTok.Ident);
NextToken ();
const SymEntry Field = FindStructField (Expr->Type, Ident);
const SymEntry Field = FindStructField (Expr->Type, CurTok.Ident);
if (Field.Type == 0) {
Error ("No field named '%s' found in '%s'", Ident, GetFullTypeName (Expr->Type));
Error ("No field named '%s' found in '%s'", CurTok.Ident, GetFullTypeName (Expr->Type));
/* Make the expression an integer at address zero */
ED_MakeConstAbs (Expr, 0, type_int);
return;
}
/* A struct/union is usually an lvalue. If not, it is a struct/union passed
** in the primary register, which is usually the result returned from a
** function. However, it is possible that this rvalue is the result of
** certain kind of operations on an lvalue such as assignment, and there
** are no reasons to disallow such use cases. So we just rely on the check
** upon function returns to catch the unsupported cases and dereference the
** rvalue address of the struct/union here all the time.
*/
if (IsTypePtr (Expr->Type) ||
(ED_IsRVal (Expr) &&
ED_IsLocPrimary (Expr) &&
Expr->Type == GetStructReplacementType (Expr->Type))) {
if (IsTypePtr (Expr->Type)) {
if (!ED_IsConst (Expr) && !ED_IsLocPrimary (Expr)) {
/* pointer->field */
if (!ED_IsQuasiConst (Expr) && !ED_IsLocPrimary (Expr)) {
/* If we have a non-const struct/union pointer that is not in the
** primary yet, load its content now.
** primary yet, load its content now to get the base address.
*/
LoadExpr (CF_NONE, Expr);
/* Clear the offset */
Expr->IVal = 0;
ED_FinalizeRValLoad (Expr);
}
/* Dereference the address expression */
ED_IndExpr (Expr);
} else if (ED_IsRVal (Expr) &&
ED_IsLocPrimary (Expr) &&
Expr->Type == GetStructReplacementType (Expr->Type)) {
/* A struct/union is usually an lvalue. If not, it is a struct/union
** passed in the primary register, which is usually the result returned
** from a function. However, it is possible that this rvalue is the
** result of certain kind of operations on an lvalue such as assignment,
** and there are no reasons to disallow such use cases. So we just rely
** on the check upon function returns to catch the unsupported cases and
** dereference the rvalue address of the struct/union here all the time.
*/
ED_IndExpr (Expr);
} else if (!ED_IsLocQuasiConst (Expr) && !ED_IsLocPrimaryOrExpr (Expr)) {
/* Load the base address into the primary (and use it as a reference
** later) if it's not quasi-const or in the primary already.