This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: How to use _Generic with bit-fields


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 <stdio.h>

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=0x1FFFFFFFF };
  (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 <joseph@codesourcery.com> 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 <tgmath.h>, 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
> joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]