Opened 21 months ago

Last modified 3 weeks ago

#282 new defect

Double Member Expressions Cannot Be Used as Lvalues

Reported by: ajbeach Owned by:
Priority: major Component: cfa-cc
Version: 1.0 Keywords: member
Cc:

Description (last modified by ajbeach) ΒΆ

Getting the address of a field of a field does not work:

forall( U & )
struct LinkData {
    U * top;
};

forall( S & )
struct Link {
    LinkData(S) data;
};

void g1(int*) {}
void g2(int**) {}
void g3(int*&) {}
void f(Link(int) * link)  {
    // This works:
    g1( link->data.top);
    // Assertion failure in convert.
    g2(&link->data.top);
    // Assertion failure in convert.
    g2(&(((*link).data).top));
    // This works:
    g2(&(*&(link->data)).top);
    // error: lvalue required as unary '&' operand
    g3( link->data.top);
}

I did some investigation of this error but was unable to find a solution. The error seems to occur in "Convert L-Value" particularly in reference type elimination when some references, and the implicit dereferences they imply, are removed.

Both CastExpr? and MemberExpr? don't currently track what there lvalue status would be in C, that may be related. I also have a note that FixDtypeStatic? may be related but I have since forgotten the rational for that.

Because the error message is triggered by convert, as translation continues and eventually the conversion may never need to happen, the initial error messages will probably change.

Change History (1)

comment:1 Changed 3 weeks ago by ajbeach

Description: modified (diff)
Keywords: member added

I found another problem that appears to be related:

forall(T &)
struct inner {
    T * basic;
};

forall(T &)
This may just be a special case of #166.
struct outer {
    inner(T) in;
};

int main() {
    outer(int) data;
    int test = -7;
    data.in.basic = &test;
}

The error message is the generated says that the generated _dtype_static_member_ is a pointer and you need to use ->.

This problem also occurs if the in field is an inline structure, that is how the problem was discovered, but the problem goes away if:

  • The nested structure uses a concrete type (inner(int) in).
  • You access a field on the outer structure, although you have to add one first.
  • The outer structure is changed to a sized polymorphic type. Changing both has the same effect and you can't change just the inner one.

The code around the static member variable is pretty confusing, I have dug into it at least three times; when this ticket was opened, just recently and when I tried to remove the variable all together (which should be possible via C code). None of these attempts got very far. There is some weird stuff, most notably an assignment of a pointer to a reference that stops working if you "fix it", and whether the problem is actually here or in a later pass (the lvalue pass is very involved, so there could be a problem there).

Note: Removed a reference to #166 which turned out to be incorrect.

Note: See TracTickets for help on using tickets.