Signedness of char (and of bit-fields) is a tristate, "signed", "unsigned"
and "".  My claim is that a difference between any two of those three
values is essentially the same kind of difference.  And so at most the
wording should be adjusted (or maybe an inform ("%<char%> and %<signed
char%> are different types" added), not the conditions for some such
warning to be given.

This explanation isn't grounded in the C definition of the types
(which is fine if you want to use some other definition of
"signedness").

In C, plain char type is neither a signed nor an unsigned integer
type, whether or not it has a sign bit.  It's a distinct type that's
incompatible with both signed char and unsigned char, and pointers
to the three types are incompatible with one another.

The only thing char, signed char, and unsigned char have in common
other than the word "char" is that they are classified as "character
types."  (Plain "char" might as well be called "character.")

It seems to me that by the interpretation you suggest, converting
a signed int* to unsigned long* should be controlled by -Wpointer-
sign when int and long have the same representation, and by
-Wincompatible-pointer-types otherwise.  (Which is not what GCC
does.)

No, because those differ between "int" and "long", not between "signed"
and "" or "unsigned" and "" as signedness.

int and long differ because they're not compatible according
to the C definition of the term, even if they have the same
size, representation, and alignment (e.g., in ILP32).

"char" and "signed char" are also incompatible, even if they
otherwise have identical properties, for the same reason (i.e.,
because the standard says they're not).

I believe the answer here hinges on the definition of the term
"signedness."  If we use the same definition as the standard,
the text of the warning is strictly speaking incorrect, and
the proposed change makes it correct.

If we define signedness differently, say as "having a sign bit,"
then the warning is appropriate in one of the two cases in the
bug but not in the other.  Which one depends on the the setting
of -fsigned-char:

  signed char   *ps = "signed";    // okay with -fsigned-char
  unsigned char *pu = "unsigned";  // okay with -fno-signed-char

and ditto for:

  extern char *p;

  ps = p;   // okay with -fsigned-char
  pu = p;   // okay with -fno-signed-char

However, this definition of signedness would imply that the
warning should not be issued for the code below (for example)
when int and long have the same size, representation, and
alignment:

  int *p = (long*)0;

Perhaps there is another definition according to which the text
of the warning would be correct in all cases.  If there is one,
it should be outlined in the documentation.  (I would recommend
using the standard definition since that's what most users are
either already familiar with or can easily look it up.)

Martin

Reply via email to