On 3/15/22 08:32, Jakub Jelinek wrote:
On Fri, Feb 11, 2022 at 12:27:49PM -0500, Jason Merrill wrote:
Yes, that's what the above code would correctly do if TYPE were the
pointer-to-method type.  It's wrong for this case because TYPE is unrelated
to TREE_TYPE (field).

I think the problem is just this line:

                 if (tree ret = c_fold_indirect_ref_for_warn (loc, type, cop,
                                                              off))
                   return ret;
                 return cop;
                   ^^^^^^^^^^

The recursive call does the proper type checking, but then the "return cop"
line returns the COMPONENT_REF even though the type check failed. The
parallel code in cxx_fold_indirect_ref_1 doesn't have this line, and
removing it fixes the testcase, so I see

warning: ‘*(ptrmemfunc*)&x.ptrmemfunc::ptr’ is used uninitialized

The intent of r11-6729 is that it prints something that helps user to figure
out what exactly is being accessed.
When we find a unique non-static data member that is being accessed, even
when we can't fold it nicely, IMNSHO it is better to print
   ((sometype *)&var)->field
or
   (*(sometype *)&var).field
instead of
   *(fieldtype *)((char *)&var + 56)
because the user doesn't know what is at offset 56, we shouldn't ask user
to decipher structure layout etc.

The problem is that the reference is *not* to any non-static data member, it's to the PMF as a whole. But c_fold_indirect_ref_for_warn wrongly turns it into a reference to the first non-static data member.

We asked c_fold_indirect_ref_warn to fold a MEM_REF with RECORD_TYPE, and it gave us back a COMPONENT_REF with POINTER_TYPE. That seems clearly wrong.

One question is if we could return something better for the TYPE_PTRMEMFUNC_FLAG
RECORD_TYPE members here (something that would print it more naturally/readably
in a C++ way), though the fact that the routine is in c-family makes it
harder.

Another one is whether we shouldn't punt for FIELD_DECLs that don't have
nicely printable name of its containing scope, something like:
                if (tree scope = get_containing_scope (field))
                  if (TYPE_P (scope) && TYPE_NAME (scope) == NULL_TREE)
                    break;
                return cop;
or so.
Note the returned cop is a COMPONENT_REF where the first argument has a
nicely printable type name (x with type sp), but sp's TYPE_MAIN_VARIANT
is the unnamed TYPE_PTRMEMFUNC_FLAG.  So another possibility would be if
we see such a problem for the FIELD_DECL's scope, check if TYPE_MAIN_VARIANT
of the first COMPONENT_REF's argument is equal to that scope and in that
case use TREE_TYPE of the first COMPONENT_REF's argument as the scope
instead.

        Jakub


Reply via email to