Re: How to use _Generic with bit-fields

2016-02-25 Thread Wink Saville
Thanks for the info. What I'll probably do is file a bug and reply to this
thread and the other one when I do.


On Thu, Feb 25, 2016, 2:50 PM Joseph Myers  wrote:
>
> On Wed, 24 Feb 2016, Wink Saville wrote:
>
> > Further more things like printing of "big" bit fields such as
> > unsigned long long int b:33 doesn't issue any warnings with -Wall on clang
>
> Of course, printing such a bit-field with %llu etc. isn't fully portable
> even with the C++ semantics for bit-field types.  With the C++ semantics,
> if int is 34 bits or more then it gets promoted to int; otherwise, if
> unsigned int is 33 bits or more then it gets promoted to unsigned int.  So
> as with many cases of using variadic functions, you need to include a cast
> to get the desired types.  It just so happens it's hard for warnings to
> tell how portable you want the code to be, or to tell whether an
> unportable format for a type was e.g. autoconf-detected to be correct.
>
> > If someone were to supply a patch that changed the behavior to match
> > what clang and apparently other compilers are doing, would you be likely
> > to accept it?
>
> Not without a clear direction from WG14 to require the C++ rules (in which
> case conditionals on the C standard version would be appropriate, given
> the previous direction from the C90 DRs).  You'd need to track the
> declared type for each bit-field alongside the reduced-width type, apply
> C++-style promotions and conversions to the declared type for relevant
> rvalue uses, and handle the types appropriately in _Generic and typeof -
> other changes could be needed if e.g. conversion from floating-point to
> bit-fields were defined to convert to the declared type and then convert
> from that to the bit-field.  (A narrower direction only defining types in
> _Generic might still require tracking declared types but not require so
> many other changes.)
>
> --
> Joseph S. Myers
> jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-25 Thread Joseph Myers
On Wed, 24 Feb 2016, Wink Saville wrote:

> Further more things like printing of "big" bit fields such as
> unsigned long long int b:33 doesn't issue any warnings with -Wall on clang

Of course, printing such a bit-field with %llu etc. isn't fully portable 
even with the C++ semantics for bit-field types.  With the C++ semantics, 
if int is 34 bits or more then it gets promoted to int; otherwise, if 
unsigned int is 33 bits or more then it gets promoted to unsigned int.  So 
as with many cases of using variadic functions, you need to include a cast 
to get the desired types.  It just so happens it's hard for warnings to 
tell how portable you want the code to be, or to tell whether an 
unportable format for a type was e.g. autoconf-detected to be correct.

> If someone were to supply a patch that changed the behavior to match
> what clang and apparently other compilers are doing, would you be likely
> to accept it?

Not without a clear direction from WG14 to require the C++ rules (in which 
case conditionals on the C standard version would be appropriate, given 
the previous direction from the C90 DRs).  You'd need to track the 
declared type for each bit-field alongside the reduced-width type, apply 
C++-style promotions and conversions to the declared type for relevant 
rvalue uses, and handle the types appropriately in _Generic and typeof - 
other changes could be needed if e.g. conversion from floating-point to 
bit-fields were defined to convert to the declared type and then convert 
from that to the bit-field.  (A narrower direction only defining types in 
_Generic might still require tracking declared types but not require so 
many other changes.)

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-24 Thread Wink Saville
On Wed, Feb 24, 2016 at 3:38 PM, Joseph Myers  wrote:
> On Wed, 24 Feb 2016, Wink Saville wrote:
>
>> > (c) nothing defines semantics of conversion of out-of-range values to
>> > bit-fields other than treating the width as part of the type (or in the
>> > case of _Bool bit-fields, having the special wording to make it explicit
>> > that those have the semantics of _Bool not the semantics of an ordinary
>> > unsigned integer type with the specified number of bits).
>>
>>
>> I don't see where in the standard it says the width of a bit field is
>> part of the type.
>> I see In Section 6.7.2.1 paragraphs 9, 10, 11, 12 requires the compiler to 
>> know
>> the width, but I don't see where the width is part of the type.
>>
>> Could you point me to the appropriate paragraph(s)?
>
> If you look at the London 2007 minutes
>  you'll see
> that at that time this was intended to be deliberately ambiguous, to
> support both C++ practice and the longstanding C intent as expressed in
> the responses to various C90 DRs (the difference, at that time, only
> mattering for implementation-defined bit-field types).
>
> The "interpreted as having a signed or unsigned integer type consisting of
> the specified number of bits" (paragraph 10), if applied for the purposes
> of interpreting other references to types in C11, has consequences
> including: (i) conversions to store a value in a bit-field follow the same
> rules as conversions to a normal integer type, (ii) a bit-field with width
> less than that of int also has integer conversion rank less than that of
> int, and so promotes to int under the integer promotions (even if the
> declared type is wider than int).

I found this very surprising, but the standard does seem to require this.

>  (It also has the less intuitive
> consequences regarding bit-field types escaping from their bit-field
> context, as discussed in the present thread and elsewhere.)
>
> Without it being part of the type, making long:1 promote to int (as in
> C++) not long would require changes to the wording on promotions, and
> separate wording would be needed to make the results of assignments clear
> (and I'm not convinced that C++ has such wording in all cases where it is
> needed).

Clang doesn't seem to need to have the width as part of the type. And by not
having it as part of the type _Generic works as expected on clang but doesn't
work on gcc.

Further more things like printing of "big" bit fields such as
unsigned long long int b:33 doesn't issue any warnings with -Wall on clang
but does on gcc. Also, the shifting weirdness doesn't occur on clang.
>From my perspective, as a user, I think these behaviors are gcc bugs.

If someone were to supply a patch that changed the behavior to match
what clang and apparently other compilers are doing, would you be likely
to accept it?

-- Wink

> --
> Joseph S. Myers
> jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-24 Thread Joseph Myers
On Wed, 24 Feb 2016, Wink Saville wrote:

> > (c) nothing defines semantics of conversion of out-of-range values to
> > bit-fields other than treating the width as part of the type (or in the
> > case of _Bool bit-fields, having the special wording to make it explicit
> > that those have the semantics of _Bool not the semantics of an ordinary
> > unsigned integer type with the specified number of bits).
> 
> 
> I don't see where in the standard it says the width of a bit field is
> part of the type.
> I see In Section 6.7.2.1 paragraphs 9, 10, 11, 12 requires the compiler to 
> know
> the width, but I don't see where the width is part of the type.
> 
> Could you point me to the appropriate paragraph(s)?

If you look at the London 2007 minutes 
 you'll see 
that at that time this was intended to be deliberately ambiguous, to 
support both C++ practice and the longstanding C intent as expressed in 
the responses to various C90 DRs (the difference, at that time, only 
mattering for implementation-defined bit-field types).

The "interpreted as having a signed or unsigned integer type consisting of 
the specified number of bits" (paragraph 10), if applied for the purposes 
of interpreting other references to types in C11, has consequences 
including: (i) conversions to store a value in a bit-field follow the same 
rules as conversions to a normal integer type, (ii) a bit-field with width 
less than that of int also has integer conversion rank less than that of 
int, and so promotes to int under the integer promotions (even if the 
declared type is wider than int).  (It also has the less intuitive 
consequences regarding bit-field types escaping from their bit-field 
context, as discussed in the present thread and elsewhere.)

Without it being part of the type, making long:1 promote to int (as in 
C++) not long would require changes to the wording on promotions, and 
separate wording would be needed to make the results of assignments clear 
(and I'm not convinced that C++ has such wording in all cases where it is 
needed).

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-24 Thread Wink Saville
See comment on (c) below

On Wed, Feb 24, 2016 at 1:53 PM Joseph Myers  wrote:
>
> On Wed, 24 Feb 2016, Martin Sebor wrote:
>
> > > That can be avoided simply by using unary + in the controlling expression
> > > of _Generic (just as using unary + will avoid an error from sizeof, if you
> > > want to be able to apply that to expressions that might be bit-fields) -
> > > or any of the other techniques for achieving promotions of selected types.
> >
> > Unfortunately, the + n trick is far too limited to be generally
> > usable.  Since GCC allows bit-fields of other integers types
> > besides those described by the standard (e.g., long long), the
> > plus expression would have to be converted to the widest possible
> > type (e.g., by (x + 0LL)) which would defeat the purpose of
> > _Generic.  The trick of course work at all for type-generic
> > macro intended to also accept non- scalar arguments.
>
> There are lots of variants of the trick (including the conditional
> expression one), depending on which types you care about distinguishing
> and which are valid arguments to the macro.  If you want, you can even
> distinguish each bit-field width wider than int individually using typeof,
> via writing expressions with typeof to determine the width of the type.
>
> I suspect many attempts to use _Generic with non-arithmetic types would
> run into usability problems in practice because every expression in the
> generic association list must still pass the Constraints whatever the type
> of the controlling expression - so you can select a function name based on
> that type, but putting more complicated expressions directly inside
> _Generic would be problematic in many cases if a wide range of types is to
> be allowed.
>
> There is a basic question: is _Generic supposed to be arbitrarily
> expressive, or is it meant to cover cases like ?  The answer in
> the context of questions about qualifiers and array-to-pointer decay was
> that it is meant to cover cases like , not to be arbitrarily
> expressive for hypothetical cases.  Maximal expressiveness would allow
> distinguishing all bit-field widths, but that would fall down on
> usability.
>
> Integer types narrower than int are effectively second-class entities in
> C; you can't write constants of those types, for example, and they get
> promoted before used in arithmetic or being passed in variable arguments;
> while you *can* select on them with _Generic, the utility of doing so may
> be limited.  Bit-fields are effectively third-class entities, and
> bit-fields with implementation-defined declared types other than int or
> signed int or unsigned int are fourth-class (not required by the standard
> at all, and have their own problems of specification - and the final
> choice for DR#315 was to leave pretty much everything about such
> bit-fields implementation-defined - see the minutes for Portland 2006,
> London 2007, Kona 2007).
>
> > GCC's handling of bit-fields in __typeof__  is also a problem
> > and causes bugs in .  For example, the following is
> > rejected by GCC (with not just one but 42 errors) as a result:
> >
> >   struct S { unsigned b: 31; } s;
> >   carg (s.b);
>
> That should be reported as an ordinary bug in , that can easily
> be addressed by using unary + so that typeof isn't applied to a bit-field
> ( treats all integer types the same and non-arithmetic types are
> irrelevant to it, so unary + is absoletely fine there).
>
> > If it isn't clear it should be brought up in WG14 and clarified.
> > It's clear enough in C++ for bit-fields to be used as arguments
> > to overloaded functions or function templates.  I can't imagine
>
> C++ has long diverged from C regarding bit-fields (allowing other declared
> types, allowing widths wider than the width of the underlying type, now
> requiring plain int bit-fields to be signed, ...).  Whereas C has its line
> of textual history going back to various C90 DRs and showing that:
>
> (a) whether a bit-field width counts of part of the type doesn't generally
> matter within the standard except for integer promotions, so can safely be
> left unspecified with just special wording for promotions (modulo the new
> _Generic issue);
>
> (b) everything about such matters for bit-fields of nonstandard types can
> be left implementation-defined;
>
> (c) nothing defines semantics of conversion of out-of-range values to
> bit-fields other than treating the width as part of the type (or in the
> case of _Bool bit-fields, having the special wording to make it explicit
> that those have the semantics of _Bool not the semantics of an ordinary
> unsigned integer type with the specified number of bits).


I don't see where in the standard it says the width of a bit field is
part of the type.
I see In Section 6.7.2.1 paragraphs 9, 10, 11, 12 requires the compiler to know
the width, but I don't see where the width is part of the type.

Could you point me to the appropriate paragraph(s)?

-- wink

>
>
> 

Re: How to use _Generic with bit-fields

2016-02-24 Thread Joseph Myers
On Wed, 24 Feb 2016, Martin Sebor wrote:

> > That can be avoided simply by using unary + in the controlling expression
> > of _Generic (just as using unary + will avoid an error from sizeof, if you
> > want to be able to apply that to expressions that might be bit-fields) -
> > or any of the other techniques for achieving promotions of selected types.
> 
> Unfortunately, the + n trick is far too limited to be generally
> usable.  Since GCC allows bit-fields of other integers types
> besides those described by the standard (e.g., long long), the
> plus expression would have to be converted to the widest possible
> type (e.g., by (x + 0LL)) which would defeat the purpose of
> _Generic.  The trick of course work at all for type-generic
> macro intended to also accept non- scalar arguments.

There are lots of variants of the trick (including the conditional 
expression one), depending on which types you care about distinguishing 
and which are valid arguments to the macro.  If you want, you can even 
distinguish each bit-field width wider than int individually using typeof, 
via writing expressions with typeof to determine the width of the type.

I suspect many attempts to use _Generic with non-arithmetic types would 
run into usability problems in practice because every expression in the 
generic association list must still pass the Constraints whatever the type 
of the controlling expression - so you can select a function name based on 
that type, but putting more complicated expressions directly inside 
_Generic would be problematic in many cases if a wide range of types is to 
be allowed.

There is a basic question: is _Generic supposed to be arbitrarily 
expressive, or is it meant to cover cases like ?  The answer in 
the context of questions about qualifiers and array-to-pointer decay was 
that it is meant to cover cases like , not to be arbitrarily 
expressive for hypothetical cases.  Maximal expressiveness would allow 
distinguishing all bit-field widths, but that would fall down on 
usability.

Integer types narrower than int are effectively second-class entities in 
C; you can't write constants of those types, for example, and they get 
promoted before used in arithmetic or being passed in variable arguments; 
while you *can* select on them with _Generic, the utility of doing so may 
be limited.  Bit-fields are effectively third-class entities, and 
bit-fields with implementation-defined declared types other than int or 
signed int or unsigned int are fourth-class (not required by the standard 
at all, and have their own problems of specification - and the final 
choice for DR#315 was to leave pretty much everything about such 
bit-fields implementation-defined - see the minutes for Portland 2006, 
London 2007, Kona 2007).

> GCC's handling of bit-fields in __typeof__  is also a problem
> and causes bugs in .  For example, the following is
> rejected by GCC (with not just one but 42 errors) as a result:
> 
>   struct S { unsigned b: 31; } s;
>   carg (s.b);

That should be reported as an ordinary bug in , that can easily 
be addressed by using unary + so that typeof isn't applied to a bit-field 
( treats all integer types the same and non-arithmetic types are 
irrelevant to it, so unary + is absoletely fine there).

> If it isn't clear it should be brought up in WG14 and clarified.
> It's clear enough in C++ for bit-fields to be used as arguments
> to overloaded functions or function templates.  I can't imagine

C++ has long diverged from C regarding bit-fields (allowing other declared 
types, allowing widths wider than the width of the underlying type, now 
requiring plain int bit-fields to be signed, ...).  Whereas C has its line 
of textual history going back to various C90 DRs and showing that:

(a) whether a bit-field width counts of part of the type doesn't generally 
matter within the standard except for integer promotions, so can safely be 
left unspecified with just special wording for promotions (modulo the new 
_Generic issue);

(b) everything about such matters for bit-fields of nonstandard types can 
be left implementation-defined;

(c) nothing defines semantics of conversion of out-of-range values to 
bit-fields other than treating the width as part of the type (or in the 
case of _Bool bit-fields, having the special wording to make it explicit 
that those have the semantics of _Bool not the semantics of an ordinary 
unsigned integer type with the specified number of bits).

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-24 Thread Martin Sebor

$ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc
-B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc z.c
struct S { unsigned i: 31; } s;
int i = _Generic (s.i, unsigned: 1);
z.c:2:19: error: ‘_Generic’ selector of type ‘unsigned int:31’ is not
compatible with any association
  int i = _Generic (s.i, unsigned: 1);
^


That can be avoided simply by using unary + in the controlling expression
of _Generic (just as using unary + will avoid an error from sizeof, if you
want to be able to apply that to expressions that might be bit-fields) -
or any of the other techniques for achieving promotions of selected types.


Unfortunately, the + n trick is far too limited to be generally
usable.  Since GCC allows bit-fields of other integers types
besides those described by the standard (e.g., long long), the
plus expression would have to be converted to the widest possible
type (e.g., by (x + 0LL)) which would defeat the purpose of
_Generic.  The trick of course work at all for type-generic
macro intended to also accept non- scalar arguments.



You can't use bit-fields with sizeof, or with unary &, or in GNU C with
typeof.  I think extending this constraint to _Generic - meaning you need
to use a trick such as unary + when a bit-field might occur there - is
consistent with the peculiar position of bit-fields in C as not quite
normal objects or types (and consistent with how _Generic is intended for
certain limited kinds of overloading such as ,


GCC's handling of bit-fields in __typeof__  is also a problem
and causes bugs in .  For example, the following is
rejected by GCC (with not just one but 42 errors) as a result:

  struct S { unsigned b: 31; } s;
  carg (s.b);

even though this is accepted:

  _Complex double cd = s.b;


not for
arbitrarily expressive logic on types, cf. the rejection of overloading on
qualifiers).  If someone uses e.g. unsigned int:8 as the controlling
expression of _Generic, it's hardly clear whether a selection for unsigned
char (a type with the same set of values), unsigned int (the declared type
ignoring width) or int (the type resulting from the integer promotions)
would be the most useful selection.


If it isn't clear it should be brought up in WG14 and clarified.
It's clear enough in C++ for bit-fields to be used as arguments
to overloaded functions or function templates.  I can't imagine
a good reason for not nailing it down in C.  Especially since
existing practice shows that it can be made to work in
unsurprising ways (all 5 GCC-compatible compilers that I've
tested accept bit-fields in __typeof__ and, those that support
it, also in _Generic).

Martin



Re: How to use _Generic with bit-fields

2016-02-22 Thread Wink Saville
Joseph,

Thanks for the unary + suggestion.

It definitely makes sense that the bit field length must be known for
handling things like assignments, but it doesn't have to be part of
the type signature.


Martin,

I've updated bug 65471: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65471


I created a simpler test program:

$ cat test.c
#include 

struct S {
  int b0:4;
  unsigned int b1:4;
  unsigned long long int b33:33;
};

#define type2str(__x) _Generic((__x), \
  int : "int", \
  unsigned int : "unsigned int", \
  unsigned long long int : "unsigned long long int", \
  default : "unknown")

int main(void) {
  struct S s = { .b0=3, .b1=4, .b33=0x1 };
  (void)s; // Not used

   // gcc | clang output
  printf("type2str(s.b0):  %s\n", type2str(s.b0)); // unknown | int
  printf("type2str(s.b1):  %s\n", type2str(s.b1)); // unknown | unsigned int
  printf("type2str(s.b33): %s\n", type2str(s.b33));// unknown |
unsigned long long int

  return 0;
}

$ cat Makefile
CC = gcc
O = 3
STD = c11
M = 32

test: test.c Makefile
$(CC) -O$(O) -m$(M) -Wall -std=$(STD) test.c -o test

clean:
rm -f test



And ran it on gcc and clang

$ make clean ; make CC=gcc ; ./test
rm -f test
gcc -O3 -m32 -Wall -std=c11 test.c -o test
type2str(s.b0):  unknown
type2str(s.b1):  unknown
type2str(s.b33): unknown

$ make clean ;make CC=clang ; ./test
rm -f test
clang -O3 -m32 -Wall -std=c11 test.c -o test
type2str(s.b0):  int
type2str(s.b1):  unsigned int
type2str(s.b33): unsigned long long int


-- Wink


On Mon, Feb 22, 2016 at 4:58 PM, Joseph Myers  wrote:
> On Mon, 22 Feb 2016, Martin Sebor wrote:
>
>> for the C standard not to support it.  (The problem is simply that
>> wording that specifies the feature was poorly chosen and GCC seems
>> to follow it a bit too strictly, and to the detriment of usability.)
>
> The wording for bit-fields, although unclear in places, elegantly
> addresses all the issues with what the semantics of assignment to
> bit-fields are (including e.g. allowing an instruction for conversion of
> floating-point to 16-bit integer, complete with raising exceptions for
> out-of-range values, to be used to convert to int:16, rather than
> requiring a conversion to int and subsequent conversion from int to
> int:16), with none of the duplication that would be involved if bit-fields
> had the underlying types and so semantics for conversions needed to be
> specified separately.  It also naturally means that e.g. unsigned long:1
> promotes to int in expressions, by the normal rules for promotions.
>
>> $ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc
>> -B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc z.c
>> struct S { unsigned i: 31; } s;
>> int i = _Generic (s.i, unsigned: 1);
>> z.c:2:19: error: ‘_Generic’ selector of type ‘unsigned int:31’ is not
>> compatible with any association
>>  int i = _Generic (s.i, unsigned: 1);
>>^
>
> That can be avoided simply by using unary + in the controlling expression
> of _Generic (just as using unary + will avoid an error from sizeof, if you
> want to be able to apply that to expressions that might be bit-fields) -
> or any of the other techniques for achieving promotions of selected types.
>
> You can't use bit-fields with sizeof, or with unary &, or in GNU C with
> typeof.  I think extending this constraint to _Generic - meaning you need
> to use a trick such as unary + when a bit-field might occur there - is
> consistent with the peculiar position of bit-fields in C as not quite
> normal objects or types (and consistent with how _Generic is intended for
> certain limited kinds of overloading such as , not for
> arbitrarily expressive logic on types, cf. the rejection of overloading on
> qualifiers).  If someone uses e.g. unsigned int:8 as the controlling
> expression of _Generic, it's hardly clear whether a selection for unsigned
> char (a type with the same set of values), unsigned int (the declared type
> ignoring width) or int (the type resulting from the integer promotions)
> would be the most useful selection.
>
> --
> Joseph S. Myers
> jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-22 Thread Joseph Myers
On Mon, 22 Feb 2016, Martin Sebor wrote:

> for the C standard not to support it.  (The problem is simply that
> wording that specifies the feature was poorly chosen and GCC seems
> to follow it a bit too strictly, and to the detriment of usability.)

The wording for bit-fields, although unclear in places, elegantly 
addresses all the issues with what the semantics of assignment to 
bit-fields are (including e.g. allowing an instruction for conversion of 
floating-point to 16-bit integer, complete with raising exceptions for 
out-of-range values, to be used to convert to int:16, rather than 
requiring a conversion to int and subsequent conversion from int to 
int:16), with none of the duplication that would be involved if bit-fields 
had the underlying types and so semantics for conversions needed to be 
specified separately.  It also naturally means that e.g. unsigned long:1 
promotes to int in expressions, by the normal rules for promotions.

> $ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc
> -B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc z.c
> struct S { unsigned i: 31; } s;
> int i = _Generic (s.i, unsigned: 1);
> z.c:2:19: error: ‘_Generic’ selector of type ‘unsigned int:31’ is not
> compatible with any association
>  int i = _Generic (s.i, unsigned: 1);
>^

That can be avoided simply by using unary + in the controlling expression 
of _Generic (just as using unary + will avoid an error from sizeof, if you 
want to be able to apply that to expressions that might be bit-fields) - 
or any of the other techniques for achieving promotions of selected types.

You can't use bit-fields with sizeof, or with unary &, or in GNU C with 
typeof.  I think extending this constraint to _Generic - meaning you need 
to use a trick such as unary + when a bit-field might occur there - is 
consistent with the peculiar position of bit-fields in C as not quite 
normal objects or types (and consistent with how _Generic is intended for 
certain limited kinds of overloading such as , not for 
arbitrarily expressive logic on types, cf. the rejection of overloading on 
qualifiers).  If someone uses e.g. unsigned int:8 as the controlling 
expression of _Generic, it's hardly clear whether a selection for unsigned 
char (a type with the same set of values), unsigned int (the declared type 
ignoring width) or int (the type resulting from the integer promotions) 
would be the most useful selection.

-- 
Joseph S. Myers
jos...@codesourcery.com

Re: How to use _Generic with bit-fields

2016-02-22 Thread Martin Sebor

On 02/21/2016 06:44 PM, Wink Saville wrote:

I've tried you hack, but it doesn't work with "long bit fields". Also,
I've run into another problem. Instead of using unsigned char for
the bit field I changed it to a long unsigned int:33 and now I can't
print it without a warning.


That's unfortunate.  As I suggested before, it would be useful to
add your test cases to bug 65471 to help bring them to the committee's
attention.  The bug submitter especially seems to be interested in
making the feature more useful and while he may not be reading this
list he is likely to notice the bug update.

The purpose of the generic selection in C is to provide a limited
form of function overloading.  Calling functions with bitfield
arguments is obviously useful regardless of the bit-field width
so it should "just work" with _Generic.  It does with other
compilers (Clang and the EDG front end) and there's no good reason
for the C standard not to support it.  (The problem is simply that
wording that specifies the feature was poorly chosen and GCC seems
to follow it a bit too strictly, and to the detriment of usability.)

I'm sorry but I can't think of a way to make this work the way you're
trying to.  Again, I encourage you to add it to the existing bug or
open a new one.

Martin

PS From some of the followups downthread it looks to me as though
the problem might be thought to be the bit-field width in your test
case exceeding that of int.  The following example shows that the
same problem error is reported even with a smaller bit-field.

$ cat z.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc 
-B/home/msebor/build/gcc-trunk-svn/gcc -Wall -Wextra -Wpedantic -xc z.c

struct S { unsigned i: 31; } s;
int i = _Generic (s.i, unsigned: 1);
z.c:2:19: error: ‘_Generic’ selector of type ‘unsigned int:31’ is not 
compatible with any association

 int i = _Generic (s.i, unsigned: 1);
   ^



Re: How to use _Generic with bit-fields

2016-02-22 Thread Joseph Myers
On Mon, 22 Feb 2016, Wink Saville wrote:

> I understand "long" bit fields are in ISO, but its a gcc extension so
> it would seem it should play nice with as much of the language as
> possible.
> 
> It seems the root of the problem here is the length encoding
> in the type, why does gcc do that, does the standard
> require it?

See the previously identified analysis of the textual history, the various 
C90 and C99 DRs involved, and how (as noted in 1993 in DR#120, and as is 
still the case) there is *no definition whatever* in ISO C of what value 
would be stored in a bit-field by an assignment of a value out of range of 
an integer type with the given number of bits, other than through the 
rules for conversions, which only apply if you consider the bit-field to 
have the restricted-width type.  (And, if you wish, you could do the 
archaeology around the many bugs that were fixed in GCC by giving 
bit-fields types reflecting the values they could actually represent.)

The root of the "problem" is using the extension of bit-fields wider than 
int, a feature that simply doesn't fit well into the C language and has 
unintuitive consequences.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-22 Thread Wink Saville
I'm sorry I meant:

I understand "long" bit lengths are NOT in ISO, "



On Mon, Feb 22, 2016 at 4:06 PM, Wink Saville  wrote:
> I understand "long" bit fields are in ISO, but its a gcc extension so
> it would seem it should play nice with as much of the language as
> possible.
>
> It seems the root of the problem here is the length encoding
> in the type, why does gcc do that, does the standard
> require it?
>
> On Mon, Feb 22, 2016 at 3:48 PM, Joseph Myers  wrote:
>> On Mon, 22 Feb 2016, Wink Saville wrote:
>>
>>> What about printing of "long" bit fields? I wonder if there should be an
>>> option which indicates that bit field types should not include their length.
>>
>> "long" bit-fields aren't even guaranteed by ISO C to be supported at all;
>> portable code must avoid them.  The portable way to print values of
>> arbitrary integer types is to cast to intmax_t / uintmax_t and then use
>> corresponding formats; that works fine with such bit-fields as well as
>> normal types.
>>
>> --
>> Joseph S. Myers
>> jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-22 Thread Wink Saville
I understand "long" bit fields are in ISO, but its a gcc extension so
it would seem it should play nice with as much of the language as
possible.

It seems the root of the problem here is the length encoding
in the type, why does gcc do that, does the standard
require it?

On Mon, Feb 22, 2016 at 3:48 PM, Joseph Myers  wrote:
> On Mon, 22 Feb 2016, Wink Saville wrote:
>
>> What about printing of "long" bit fields? I wonder if there should be an
>> option which indicates that bit field types should not include their length.
>
> "long" bit-fields aren't even guaranteed by ISO C to be supported at all;
> portable code must avoid them.  The portable way to print values of
> arbitrary integer types is to cast to intmax_t / uintmax_t and then use
> corresponding formats; that works fine with such bit-fields as well as
> normal types.
>
> --
> Joseph S. Myers
> jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-22 Thread Joseph Myers
On Mon, 22 Feb 2016, Wink Saville wrote:

> What about printing of "long" bit fields? I wonder if there should be an
> option which indicates that bit field types should not include their length.

"long" bit-fields aren't even guaranteed by ISO C to be supported at all; 
portable code must avoid them.  The portable way to print values of 
arbitrary integer types is to cast to intmax_t / uintmax_t and then use 
corresponding formats; that works fine with such bit-fields as well as 
normal types.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-22 Thread Joseph Myers
I wonder if ISO C really ought to have a new Constraint "The controlling 
expression of a generic selection shall not be an expression that 
designates a bit-field member." (so requiring a diagnostic), much like 
such expressions being disallowed in sizeof, to reflect the special nature 
of bit-fields and their types in C.  Or, more weakly, to allow the cbrt 
example, "If the controlling expression of a generic selection is an 
expression that designates a bit-field member, it is unspecified whether 
the type of that expression is considered compatible with any integer 
types named in its generic association list.".

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-21 Thread Wink Saville
I've tried you hack, but it doesn't work with "long bit fields". Also,
I've run into another problem. Instead of using unsigned char for
the bit field I changed it to a long unsigned int:33 and now I can't
print it without a warning.

Here is my Makefile:

CC = gcc
O = 3
X = c
STD = c11

CFLAGS = -m64 -Wall -std=$(STD)

all: test

test.o: test.c
$(CC) -x $(X) -O$(O) $(CFLAGS) -o test.o -c test.c
objdump -d test.o > test.txt

test: test.o
$(CC) $(CFLAGS) test.o -o test

clean:
rm -f test test.o test.txt

Here is the test:

#include 

struct big_bit_fields {
  long unsigned int b33:33;
} __attribute__((__packed__));

_Static_assert(sizeof(struct big_bit_fields) == 5,
L"big_bit_fields is not 5 bytes");


#define type_to_str(__x) _Generic((0)?(__x):(__x), \
  _Bool : "_Bool", \
  char : "char", \
  signed char : "unsigned char", \
  unsigned char : "unsigned char", \
  short int : "short int", \
  unsigned short int: "unsigned short int", \
  int : "int", \
  unsigned int : "unsigned int", \
  long int : "long int", \
  long unsigned int : "long unsigned int", \
  long long int : "long long int", \
  long long unsigned int : "long long unsigned int", \
  default : "unknown type")

int main(void) {
  struct big_bit_fields bbf = { .b33 = 0x1 };

  printf("bbf.b33=0x%lx\n", bbf.b33);
  printf("   type=%s\n", type_to_str(bbf.b33));
  printf("   <<1 =0x%016lx\n", bbf.b33 << 1);
  printf("  (ull)<<1 =0x%016lx\n", (long unsigned int)bbf.b33 << 1);

  return 0;
}


Here the compile and run:

$ make clean ; make ; ./test
rm -f test test.o test.txt
gcc -x c -O3 -m64 -Wall -std=c11 -o test.o -c test.c
test.c: In function ‘main’:
test.c:44:10: warning: format ‘%lx’ expects argument of type ‘long
unsigned int’, but argument 2 has type ‘long unsigned int:33’
[-Wformat=]
   printf("bbf.b33=0x%lx\n", bbf.b33);
  ^
test.c:46:10: warning: format ‘%lx’ expects argument of type ‘long
unsigned int’, but argument 2 has type ‘long unsigned int:33’
[-Wformat=]
   printf("   <<1 =0x%016lx\n", bbf.b33 << 1);
  ^
objdump -d test.o > test.txt
gcc -m64 -Wall -std=c11 test.o -o test
bbf.b33=0x1
   type=unknown type
   <<1 =0x0001fffe
  (ull)<<1 =0x0003fffe




On Fri, Feb 19, 2016 at 1:35 PM, Martin Sebor  wrote:
> On 02/19/2016 11:25 AM, Wink Saville wrote:
>>
>> I'm using gcc 5.3.0:
>>
>> $ gcc --version
>> gcc (GCC) 5.3.0
>> Copyright (C) 2015 Free Software Foundation, Inc.
>> This is free software; see the source for copying conditions.  There is NO
>> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
>> PURPOSE.
>>
>>
>> And I've tried to use _Generic to print the type of a bit field but
>> the compiler fails with:
>>
>> $ make
>> gcc -Wall -std=c11 -o test.o -c test.c
>> test.c: In function ‘main’:
>> test.c:8:35: error: ‘_Generic’ selector of type ‘unsigned char:2’ is
>> not compatible with any association
>>   #define type_to_str(__x) _Generic((__x), \
>> ^
>> test.c:17:18: note: in expansion of macro ‘type_to_str’
>> printf("%s\n", type_to_str(b.f1));
>>^
>> Makefile:7: recipe for target 'test.o' failed
>> make: *** [test.o] Error 1
>> bash: ./test: No such file or directory
>>
>>
>> The test program is:
>>
>> $ cat test.c
>> #include 
>>
>> struct bits {
>>unsigned char f0;
>>unsigned char f1:2;
>> };
>>
>> #define type_to_str(__x) _Generic((__x), \
>>unsigned char : "unsigned char")
>>
>> int main(void) {
>>struct bits b = { .f0 = 255, .f1 = 3 };
>>
>>printf("%d\n", b.f0);
>>printf("%s\n", type_to_str(b.f0));
>>printf("%d\n", b.f1);
>>printf("%s\n", type_to_str(b.f1));
>>
>>return 0;
>> }
>>
> ...
>>
>> How do I create a type association for a bit field?
>
>
> I suspect this falls under the set of issues that fall under bug
> 65471 - type interpretation in _Generic.  The C language rules
> for _Generic aren't completely clear about what conversions are
> to take place.  It would be helpful if you could your test case
> to the bug to make sure the bitfield case is considered when
> the issue is discussed by the C committee.
>
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65471
>
> The only idea for a workaround that comes to mind is to trick GCC
> into forgetting that it's a bit-field.  This hack seems to work:
>
>   #define type_to_str(__x) _Generic((0)?(__x):(__x), \
>
> Martin
>


Re: How to use _Generic with bit-fields

2016-02-19 Thread Joseph Myers
On Fri, 19 Feb 2016, Wink Saville wrote:

> And I've tried to use _Generic to print the type of a bit field but
> the compiler fails with:

Indeed, bit-field types cannot match any type name, only default.  The 
only conversions applied to the controlling expression are those involved 
in lvalue to rvalue conversion (at least, that's what's currently 
implemented, and is the current direction on DR#481).  In particular, the 
integer promotions (which would convert this bit-field to int) are not 
applied.

You can of course use unary + (or various other constructs depending on 
the set of possible types) to cause some promotions.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: How to use _Generic with bit-fields

2016-02-19 Thread Martin Sebor

On 02/19/2016 11:25 AM, Wink Saville wrote:

I'm using gcc 5.3.0:

$ gcc --version
gcc (GCC) 5.3.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


And I've tried to use _Generic to print the type of a bit field but
the compiler fails with:

$ make
gcc -Wall -std=c11 -o test.o -c test.c
test.c: In function ‘main’:
test.c:8:35: error: ‘_Generic’ selector of type ‘unsigned char:2’ is
not compatible with any association
  #define type_to_str(__x) _Generic((__x), \
^
test.c:17:18: note: in expansion of macro ‘type_to_str’
printf("%s\n", type_to_str(b.f1));
   ^
Makefile:7: recipe for target 'test.o' failed
make: *** [test.o] Error 1
bash: ./test: No such file or directory


The test program is:

$ cat test.c
#include 

struct bits {
   unsigned char f0;
   unsigned char f1:2;
};

#define type_to_str(__x) _Generic((__x), \
   unsigned char : "unsigned char")

int main(void) {
   struct bits b = { .f0 = 255, .f1 = 3 };

   printf("%d\n", b.f0);
   printf("%s\n", type_to_str(b.f0));
   printf("%d\n", b.f1);
   printf("%s\n", type_to_str(b.f1));

   return 0;
}


...

How do I create a type association for a bit field?


I suspect this falls under the set of issues that fall under bug
65471 - type interpretation in _Generic.  The C language rules
for _Generic aren't completely clear about what conversions are
to take place.  It would be helpful if you could your test case
to the bug to make sure the bitfield case is considered when
the issue is discussed by the C committee.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65471

The only idea for a workaround that comes to mind is to trick GCC
into forgetting that it's a bit-field.  This hack seems to work:

  #define type_to_str(__x) _Generic((0)?(__x):(__x), \

Martin



How to use _Generic with bit-fields

2016-02-19 Thread Wink Saville
I'm using gcc 5.3.0:

$ gcc --version
gcc (GCC) 5.3.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


And I've tried to use _Generic to print the type of a bit field but
the compiler fails with:

$ make
gcc -Wall -std=c11 -o test.o -c test.c
test.c: In function ‘main’:
test.c:8:35: error: ‘_Generic’ selector of type ‘unsigned char:2’ is
not compatible with any association
 #define type_to_str(__x) _Generic((__x), \
   ^
test.c:17:18: note: in expansion of macro ‘type_to_str’
   printf("%s\n", type_to_str(b.f1));
  ^
Makefile:7: recipe for target 'test.o' failed
make: *** [test.o] Error 1
bash: ./test: No such file or directory


The test program is:

$ cat test.c
#include 

struct bits {
  unsigned char f0;
  unsigned char f1:2;
};

#define type_to_str(__x) _Generic((__x), \
  unsigned char : "unsigned char")

int main(void) {
  struct bits b = { .f0 = 255, .f1 = 3 };

  printf("%d\n", b.f0);
  printf("%s\n", type_to_str(b.f0));
  printf("%d\n", b.f1);
  printf("%s\n", type_to_str(b.f1));

  return 0;
}

And the Makefile is:

$ cat Makefile
CC = gcc
CFLAGS = -Wall -std=c11

all: test

test.o: test.c
$(CC) $(CFLAGS) -o test.o -c test.c

test: test.o
$(CC) $(CFLAGS) test.o -o test

clean:
rm -f test test.o test.txt


My type_to_str macro seems correct, as all is well if I comment out the last
printf:

$ cat test.c
#include 

struct bits {
  unsigned char f0;
  unsigned char f1:2;
};

#define type_to_str(__x) _Generic((__x), \
  unsigned char : "unsigned char")

int main(void) {
  struct bits b = { .f0 = 255, .f1 = 3 };

  printf("%d\n", b.f0);
  printf("%s\n", type_to_str(b.f0));
  printf("%d\n", b.f1);
  //printf("%s\n", type_to_str(b.f1));

  return 0;
}


It then compiles and runs successfully:

$ make
gcc -Wall -std=c11 -o test.o -c test.c
gcc -Wall -std=c11 test.o -o test
$ ./test
255
unsigned char
3


How do I create a type association for a bit field?