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