type checking: Unable to properly compute the operand value for an address of a nested field
This gcc test case (pr43784.c)
struct s {
unsigned char a[256];
};
union u {
struct { struct s b; int c; } d;
struct { int c; struct s b; } e;
};
static union u v;
static struct s *p = &v.d.b;
static struct s *q = &v.e.b;
static struct s __attribute__((noinline)) rp(void)
{
return *p;
}
static void qp(void)
{
*q = rp();
}
int main()
{
int i;
for (i = 0; i < 256; i++)
p->a[i] = i;
qp();
for (i = 0; i < 256; i++)
if (q->a[i] != i)
__builtin_abort();
return 0;
}
fails in qbe for the line static struct s *p = &v.d.b;
. Taking &v.d
works fine. The fix is
diff --git a/v3/check.go b/v3/check.go
index a6779e0..57b6a46 100644
--- a/v3/check.go
+++ b/v3/check.go
@@ -1455,13 +1455,13 @@ func (n *PostfixExpression) addrOf(ctx *context) Operand {
case PostfixExpressionCall: // PostfixExpression '(' ArgumentExpressionList ')'
panic(n.Position().String())
case PostfixExpressionSelect: // PostfixExpression '.' IDENTIFIER
- op := n.PostfixExpression.check(ctx, false)
+ op := n.PostfixExpression.addrOf(ctx)
n.IsSideEffectsFree = n.PostfixExpression.IsSideEffectsFree
if d := n.PostfixExpression.Declarator(); d != nil {
setAddressTaken(n, d, "PostfixExpression '.' IDENTIFIER")
d.Read += ctx.readDelta
}
- st := op.Type()
+ st := op.Type().Elem()
if k := st.Kind(); k == Invalid || k != Struct && k != Union {
//TODO report error
break
jnml@3900x:~/src/modernc.org/cc/v3$
The fix will now be pushed and tested by the builders. Heads up @dennwc and @TotallyGamerJet, the fix has the potential to break existing client code. It actually did break ccgo, though the fix is only
diff --git a/v3/lib/go.go b/v3/lib/go.go
index 863c37a..d684dd3 100644
--- a/v3/lib/go.go
+++ b/v3/lib/go.go
@@ -10671,6 +10671,9 @@ func (p *project) bitFldOff(t cc.Type, tok cc.Token) {
}
func (p *project) fldOff(t cc.Type, tok cc.Token) {
+ if t.Kind() == cc.Ptr {
+ t = t.Elem()
+ }
var off uintptr
fld, ok := t.FieldByName(tok.Value)
switch {
Sorry for the potential break, but this is correcting wrong code and wrong type of the operand that the type checker was producing.
QBE was not broken by this, it now just passes one more test (pr43784.c).
Edited by cznic