Hi, Jason,

> On Feb 11, 2022, at 11:27 AM, Jason Merrill <ja...@redhat.com> wrote:
>>>> 
>>>> Sure, we might as well make this code more robust.  But we can do better 
>>>> than <unnamed type> if we check TYPE_PTRMEMFUNC_P.
>>> Okay, so what should we print to the user if it's “TYPE_PTRMEMFUNC_P”? 
>>> Print nothing or some special string?
>>>> 
>>>>> 2. The second level issue is what you suggested in the above, shall we 
>>>>> print the “compiler generated internal type”  to the user? And I agree 
>>>>> with you that it might not be a good idea to print such compiler internal 
>>>>> names to the user.  Are we do this right now in general? (i.e, check 
>>>>> whether the current TYPE is a source level TYPE or a compiler internal 
>>>>> TYPE, and then only print out the name of TYPE for the source level 
>>>>> TYPE?) and is there a bit in the TYPE to distinguish whether a TYPE is 
>>>>> user -level type or a compiler generated internal type?
>>>> 
>>>>>> I think the real problem comes sooner, when c_fold_indirect_ref_for_warn 
>>>>>> turns a MEM_REF with RECORD_TYPE into a COMPONENT_REF with POINTER_TYPE.
>>>> 
>>>>> What’s the major issue for this transformation? (I will study this in 
>>>>> more details).
>>>> 
>>>> We told c_fold_indirect_ref that we want a RECORD_TYPE (the PMF as a 
>>>> whole) and it gave us back a POINTER_TYPE instead (the __pmf member). 
>>>> Folding shouldn't change the type of an expression like that.
>>> 
>>> Yes, this is not correct transformation, will study in more detail and try 
>>> to fix it.
>> After a deeper study of commit  r11-6729-gadb520606ce3e1e1 (which triggered 
>> the ICE and introduced the new routine “c_fold_indirect_ref_for_warn”), from 
>> my understanding,  the above transformation from a RECORD_TYPE (the PMF as a 
>> whole) to POINTER_TYPE (the __pmf member) is what the function intended to 
>> do as following:
>> 1823 static tree
>> 1824 c_fold_indirect_ref_for_warn (location_t loc, tree type, tree op,
>> 1825                               offset_int &off)
>> 1826 {
>> …
>> 1870 */* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */*
>> 1871   else if (TREE_CODE (optype) == RECORD_TYPE)
>> 1872     {
>> 1873       for (tree field = TYPE_FIELDS (optype);
>> 1874            field; field = DECL_CHAIN (field))
>> 1875         if (TREE_CODE (field) == FIELD_DECL
>> …
>> 1886 if(upos <= off && off < upos + el_sz)
>> 1887               {
>> 1888                 tree cop = build3_loc (loc, COMPONENT_REF, TREE_TYPE 
>> (field),
>> 1889                                       op, field, NULL_TREE);
>> 1890                 off = off - upos;
>> The above code was used to transform a MEM_REF to a RECORD_TYPE to a 
>> COMPONENT_REF to the corresponding FIELD.
> 
> 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,

Just compared the routine “cxx_fold_indirect_ref_1” and 
“c_fold_indirect_ref_for_warn”, looks like there are more places that have such 
difference, for example, 
In “cxx_fold_indirect_ref_1”:

  /* ((foo *)&fooarray)[x] => fooarray[x] */
  else if (TREE_CODE (optype) == ARRAY_TYPE
           && tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (optype)))
           && !integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (optype))))
…
      if (tree_fits_uhwi_p (min_val))
        {
          tree index = size_int (idx + tree_to_uhwi (min_val));
          op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index,
                           NULL_TREE, NULL_TREE);         
          return cxx_fold_indirect_ref_1 (ctx, loc, type, op, rem,
                                          empty_base);
        }
However, in “c_fold_indirect_ref_for_warn”, the corresponding part is:

  /* ((foo *)&fooarray)[x] => fooarray[x] */
  if (TREE_CODE (optype) == ARRAY_TYPE
      && TYPE_SIZE_UNIT (TREE_TYPE (optype))
      && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (optype))) == INTEGER_CST
      && !integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (optype))))
…
      if (TREE_CODE (min_val) == INTEGER_CST)
        {
          tree index
            = wide_int_to_tree (sizetype, idx + wi::to_offset (min_val));
          op = build4_loc (loc, ARRAY_REF, TREE_TYPE (optype), op, index,
                           NULL_TREE, NULL_TREE);
          off = rem;
          if (tree ret = c_fold_indirect_ref_for_warn (loc, type, op, off))
            return ret;
          return op;
        }

The exactly same difference as for “RECORD_TYPE”. So, I suspect that it’s a 
typo for “RECORD_TYPE” in “c_fold_indirect_ref_for_warn”. 

> and removing it fixes the testcase, so I see
> 
> warning: ‘*(ptrmemfunc*)&x.ptrmemfunc::ptr’ is used uninitialized


The question is:

For the following IR:

  struct sp x;
  void (*<T389>) (void) _1;
 ...
  <bb 2> [local count: 1073741824]:
  _1 = MEM[(struct ptrmemfunc_U *)&x].ptr;
  _7 = _1 != 8B;

Which message is better:

1. warning: ‘*(ptrmemfunc*)&x.ptrmemfunc::ptr’ is used uninitialized
Or
2. warning: ‘*(ptrmemfunc*)((char*)&x + offsetof(void 
(S::*)(),__PTRMEMFUNC)).ptrmemfunc::ptr’ is used uninitialized

From the source code:

====
struct S
{
  int j;
};
struct T : public S
{
  virtual void h () {}
};
struct ptrmemfunc
{
  void (*ptr) ();
};
typedef void (S::*sp)();
int main ()
{
  T t;
  sp x;
  ptrmemfunc *xp = (ptrmemfunc *) &x;
  if (xp->ptr != ((void (*)())(sizeof(void *))))
    return 1;
}
====

The reference “xp->ptr” went through from “x” to “xp”, and there is a clear 
type casting from S::__PTRMEMFUNC to ptrmemfunc::ptr. 
Shall we emit such type casting to the user?

Qing

> Jason
> 

Reply via email to