This is an archive of the discontinued LLVM Phabricator instance.

Avoid narrowing warnings in __bitset constructor
ClosedPublic

Authored by dim on Aug 27 2016, 7:52 AM.

Details

Summary

When I compile <bitset> is compiled with warnings enabled, I get the
following error (which is interesting in itself, it should only be a
warning):

/usr/include/c++/v1/bitset:265:16: error: non-constant-expression cannot be narrowed from type 'unsigned long long' to '__storage_type' (aka 'unsigned int') in
      initializer list [-Wc++11-narrowing]
    : __first_{__v, __v >> __bits_per_word}
               ^~~
/usr/include/c++/v1/bitset:676:52: note: in instantiation of member function 'std::__1::__bitset<2, 53>::__bitset' requested here
        bitset(unsigned long long __v) _NOEXCEPT : base(__v) {}
                                                   ^
/home/dim/src/llvm/trunk/include/llvm/IR/Attributes.h:455:9: note: in instantiation of member function 'std::__1::bitset<53>::bitset' requested here
      : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
        ^
/usr/include/c++/v1/bitset:265:16: note: insert an explicit cast to silence this issue
    : __first_{__v, __v >> __bits_per_word}
               ^~~

Note that this is on i386, so this uses the #elif part of the
__bitset constructor:

__bitset<_N_words, _Size>::__bitset(unsigned long long __v) _NOEXCEPT
#ifndef _LIBCPP_HAS_NO_CONSTEXPR
#if __SIZEOF_SIZE_T__ == 8
    : __first_{__v}
#elif __SIZEOF_SIZE_T__ == 4
    : __first_{__v, __v >> __bits_per_word}
#else
#error This constructor has not been ported to this platform
#endif
#endif

Indeed, __first_ has type __storage_type, which is 32 bits on this
platform, so I think an explicit static_cast is required here.

Diff Detail

Repository
rL LLVM

Event Timeline

dim updated this revision to Diff 69489.Aug 27 2016, 7:52 AM
dim retitled this revision from to Avoid narrowing warnings in __bitset constructor.
dim updated this object.
dim added reviewers: mclow.lists, EricWF.
dim added subscribers: emaste, cfe-commits.
EricWF added inline comments.Sep 1 2016, 11:00 AM
include/bitset
262 ↗(On Diff #69489)

Only the first one actually requires a cast, correct? The second should never be a potentially narrowing conversion.

dim added inline comments.Sep 1 2016, 3:39 PM
include/bitset
262 ↗(On Diff #69489)

No, originally I got two separate warnings for this:

/usr/include/c++/v1/bitset:265:16: error: non-constant-expression cannot be narrowed from type 'unsigned long long' to '__storage_type' (aka 'unsigned int') in initializer list [-Wc++11-narrowing]
    : __first_{__v, __v >> __bits_per_word}
               ^~~
/usr/include/c++/v1/bitset:676:52: note: in instantiation of member function 'std::__1::__bitset<2, 53>::__bitset' requested here
        bitset(unsigned long long __v) _NOEXCEPT : base(__v) {}
                                                   ^
contrib/llvm/include/llvm/IR/Attributes.h:455:9: note: in instantiation of member function 'std::__1::bitset<53>::bitset' requested here
      : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0),
        ^
/usr/include/c++/v1/bitset:265:16: note: insert an explicit cast to silence this issue
    : __first_{__v, __v >> __bits_per_word}
               ^~~
/usr/include/c++/v1/bitset:265:21: error: non-constant-expression cannot be narrowed from type 'unsigned long long' to '__storage_type' (aka 'unsigned int') in initializer list [-Wc++11-narrowing]
    : __first_{__v, __v >> __bits_per_word}
                    ^~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/v1/bitset:265:21: note: insert an explicit cast to silence this issue
    : __first_{__v, __v >> __bits_per_word}
                    ^~~~~~~~~~~~~~~~~~~~~~
EricWF accepted this revision.Sep 1 2016, 5:07 PM
EricWF edited edge metadata.

LGTM. Sorry this took so long. I was confused about the narrowing rules.

This revision is now accepted and ready to land.Sep 1 2016, 5:07 PM
dim added a comment.Sep 2 2016, 1:56 PM

@mclow.lists, I tested code generation (on i386-freebsd) with this small sample program:

#include <bitset>

void f(const std::bitset<53>&);

void g(void)
{
  std::bitset<53> bs(0x1234567890abcdef);
  f(bs);
}

The assembly doesn't change at all after this fix:

g():                                  # @g()
        .cfi_startproc
# BB#0:                                 # %entry
        pushl   %ebp
.Ltmp0:
        .cfi_def_cfa_offset 8
.Ltmp1:
        .cfi_offset %ebp, -8
        movl    %esp, %ebp
.Ltmp2:
        .cfi_def_cfa_register %ebp
        andl    $-8, %esp
        subl    $16, %esp
        movl    $-1867788817, 8(%esp)   # imm = 0xFFFFFFFF90ABCDEF
        movl    $305419896, 12(%esp)    # imm = 0x12345678
        leal    8(%esp), %eax
        movl    %eax, (%esp)
        calll   f(std::__1::bitset<53u> const&)
        movl    %ebp, %esp
        popl    %ebp
        retl
This revision was automatically updated to reflect the committed changes.