------- Comment #37 from matz at gcc dot gnu dot org 2007-06-05 18:24 ------- > We are pointing to cell, and using that to access cell.i
No. We are pointing to cell.ii, and use that pointer to access cell.ii.i (via in->i). Hence of course the points-to set of 'in' needs to include cell.in.i (or cell.i, as the point-to debug dump likes to call it). At least how the points-to solver is used. Theoretically it would of course be more sensible to only note that 'in' can point to 'cell.ii', and make the user of that information recognize that this actually is a structure, and hence over that pointer you can access all members of it. But that's not how the info is used, so we have to include cell.ii.i in the points to set (which in our case rather is a can-access set). Now, regarding where to fix it properly: if you say that solution_set_add() is not the right place (and I don't buy that yet, because something is wrong with it no matter what, e.g. looking for subfields starting from the things in the pt set, which themself might be subfields feels wrong), then we must not use pointer arithmetic (or at least '+' constraints) to represent pointing to substructures. And I'm not sure that's easily doable. Because the insn we see is not "in = &cell.in", but "in = &o->in", and only the pt solver itself sees that 'o' points to cell. So what constraints do you suggest should be added instead of offseted constraints for this insn? > You don't want to play in solution_set_add, which is common to a bunch of > code. Well, it's common to exactly the code which handles offsetted constraints. And I don't see why the problem we face here (with offseted copy constraints) doesn't also occur with any other of the offseted constraints, e.g. "*x = y+32", handled in do_ds_constraint. > > You can never get back to the parent structure from a pointer to the > > substructure. > > I asked this explicitly and was told it was undefined behavior. > > Yep, this is what I convinced myself aswell. Well, it's perhaps illegal in C (I'm not sure about that actually), but certainly occurs in C++, and even if it didn't occur there we are talking about the middle-end, for which such invalidity shouldn't matter (except we choose to define it as invalid). To see why this is valid, consider this C++ program: struct A {int a;}; struct B {int b;}; struct C : public A, B { int c;}; C* b2c (B* b) { return (C*)b; } C* get_c (void) { static C c; B *pb; C *pc; pb = &c; pc = (C*)pb; return pc; } This is completely valid (suppose b2c is only ever called with pointers to the B-in-C base of any C), and results in this insn: b.2_3 = (struct C *) b_2(D); D.2496_4 = b.2_3 - 4; A better example might be the other function 'get_c', which also has the subtraction: pb_3 = (struct CD.2478 *) &cD.2495.D.2482; pc_4 = pb_3 - 4; return pc_4; This currently only works because points-to gives up on subtraction and adds INTEGER to the access set of pc_4 (additionally to c.b and c.c; c.a or c itself are missing). -- matz at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |matz at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30252