On Wed, Oct 05, 2016 at 10:43:00PM -0400, Jason Merrill wrote:
> On Wed, Oct 5, 2016 at 4:02 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> > +    case INTEGER_TYPE:
> > +      return TYPE_PRECISION (t) == GET_MODE_PRECISION (TYPE_MODE (t));
> > +
> > +    case BOOLEAN_TYPE:
> > +      /* For bool values other than 0 and 1 should only appear with
> > +        undefined behavior.  */
> > +      return true;
> > +
> > +    case ENUMERAL_TYPE:
> > +      return type_has_unique_obj_representations (ENUM_UNDERLYING_TYPE 
> > (t));
> 
> I would think that we want the same answer for bool and enums: Either
> the whole type size participates in the value representation, but only
> certain values have defined behavior (so we should return true), or
> only certain bits participate in the value representation (so we
> should return false).  This is a question for the committee, but I'm
> inclined to use the INTEGER_TYPE code for BOOLEAN_TYPE and
> ENUMERAL_TYPE as well, since we don't mask off the other bits when
> loading one of these types.

The reason for the TYPE_PRECISION (t) == GET_MODE_PRECISION (TYPE_MODE (t))
is mainly worry about weirdo targets, as C++ only has the bitfield types
in the structures and that is handled in the other routine.  So the
expectations are that for INTEGER_TYPE/BOOLEAN_TYPE/ENUMERAL_TYPE we'll just
return true on sane architectures.  What I'm worried about is say __int24 or
similar types (I think AVR has them), but maybe even those are fine.
The problems would be like with the x86 XFmode long double, where a store of
that type doesn't occupy all the bytes.  Perhaps we can just return true
for all the 3 above and add a target hook that can override it first.

Returning true rather than false for bool has came up from lengthy IRC
discussions, if a value other than 0 or 1 ends up in those bytes, it will
be either through uninitializing those, or through e.g. using non-active
union member, or through aliasing violations.  But we don't really expect
those other values in there, e.g. for bool b; ... if (b) foo (); we
just compare the whole byte against 0 (if we did that consistently
everywhere, we could say we define bool as 0 being false and anything != 0
being true and std::has_unique_object_representations would need to return
false), but if one converts bool to say unsigned char, we don't do any
comparison, just simple assignment.

> 
> > +    case POINTER_TYPE:
> > +    case REFERENCE_TYPE:
> > +      return true;
> 
> Is this true for all targets?  Aren't there some pointer modes that
> only take up part of a word?

I'm not sure.  I'm slightly worried about s390 31-bit (where the top bit is
kind of ignored by the HW), but most likely we are fine, because we just
store all 32 bits when storing pointers, and in all normal addresses the top
bit will be clear, so it acts like bool, the upper bit in a valid program
will be 0.  And then about m32c or whatever arch has those 24-bit
pointers with size of 32-bits.  The question is, does the HW or compiler
store zeros in the remaining bits all the times, so it acts like a bool,
or are the bits real padding?

> > +    else if (DECL_C_BIT_FIELD (field))
> > +      {
> > +       tree btype = DECL_BIT_FIELD_TYPE (field);
> > +       if (!type_has_unique_obj_representations (btype))
> > +         return false;
> > +      }
> 
> C++ allows a bit-field to be larger than the type needs, in which case
> we should return false.

I'll look at this and add testcase; I wonder if it isn't caught during
the in-between field padding checks later on.  It would be if DECL_SIZE
of the bitfield is maxed at the DECL_BIT_FIELD_TYPE's bitsize, and the
remaining bits are gaps in between fields.

Reminds me to look at bitfields in unions.

        Jakub

Reply via email to