lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Fixing build with clang 7 and 64-bit Linux


From: Greg Chicares
Subject: Re: [lmi] Fixing build with clang 7 and 64-bit Linux
Date: Tue, 13 Nov 2018 09:57:48 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0

On 2018-11-12 22:24, Vadim Zeitlin wrote:
> On Mon, 12 Nov 2018 18:06:14 +0000 Greg Chicares <address@hidden> wrote:
> 
> GC> On 2018-11-11 19:52, Vadim Zeitlin wrote:
> GC> [...]
> GC> >         https://github.com/vadz/lmi/pull/103
> GC> 
> GC> 
> https://github.com/vadz/lmi/pull/103/commits/07fba915f6d250dfab5ee06bc79fe88ac75efeef
> GC> | facets.cpp:118:50: error: constant expression evaluates to -8193 which
> GC> | cannot be narrowed to type 'std::ctype_base::mask' (aka 'unsigned
> GC> | short') [-Wc++11-narrowing]
> GC> |
> GC> | when using clang by simply removing the braces, which impose C++11
> GC> | initialization and forbidding narrowing, and allowing the implicit cast
> GC> | to unsigned short to take place.
> GC> ...
> GC> |             // See "Implementation note" above.
> GC> | -           constexpr std::ctype_base::mask z = 
> {~std::ctype_base::space};
> GC> | +           constexpr std::ctype_base::mask z = ~std::ctype_base::space;
> GC> 
> GC> See the cited "Implementation note". I think that one or more of
> GC>   {gcc; clang; the C++11 and C++17 standards}
> GC> is incorrect.
> 
>  Sorry, I didn't mention it because I thought it was implicitly clear, but
> my assumption was, and still is, that this is a gcc defect because a
> variable of unsigned type just can't be brace-initialized with a negative
> value, which ~std::ctype_base::space clearly is (at least under Linux).

We seem to be looking at this in completely different ways, apparently
because we have different answers to a particular question pertaining
to Dietmar Kuehl's original C98 code: given
  static std::ctype_base::mask rc[table_size];
  rc[C] &= ~std::ctype_base::space;
what is the type of the expression
           ~std::ctype_base::space
on the RHS of the assignment? I don't doubt your observation that its
value is negative (and its type is therefore not unsigned) in a
particular implementation whose "mask" type is unsigned; I just think
the standard forbids that.

I believe that expression's type must be 'ctype_base::mask':

 - 'ctype_base::mask' is a "bitmask" type (C++17 [locale.types]);

 - the implementation
      constexpr bitmask operator~(bitmask X){
      return static_cast<bitmask>(~static_cast<int_type>(X));
      }
   [bitmask.types/2] is normative.

Moreover, the language "To clear a value Y in an object X is to
evaluate the expression X &= ~Y" in [locale.types/2] is certainly
normative, so issuing a warning on 'X &= ~Y' is extraordinary.

I'd conclude that the line that clang objects to:

> GC> | -           constexpr std::ctype_base::mask z = 
> {~std::ctype_base::space};

can't be wrong. It would appear that, instead of the normative

      constexpr bitmask operator~(bitmask X){
      return static_cast<bitmask>(~static_cast<int_type>(X));
      }

gcc and clang are using something like this:

      constexpr int_type operator~(bitmask X){
      return ~static_cast<int_type>(X);
      }

which seems to contradict the standard.

I could fabricate a rationale for what we've actually observed:

 - employing a typedef like
     using ctype_base::mask = unsigned short int
   is expedient (because it's probably more compact than 'int');

 - operator~()(unsigned short int) involves integral promotion;

 - thus, Kuehl's original code
     rc[C] &= ~std::ctype_base::space;
   may legitimately trigger warnings, and introducing '{}' thus:
     rc[C] &= {~std::ctype_base::space};
   renders such code certainly incorrect.

However, isn't that just to say that the signature
   constexpr bitmask operator~(bitmask)
prescribed by the standard can be ignored if one wishes?



reply via email to

[Prev in Thread] Current Thread [Next in Thread]