Opened 12 years ago

Closed 12 years ago

#4184 closed Bugs (fixed)

compiler warnings in VC9

Reported by: Michael Stellmann <stellmann@…> Owned by: nasonov
Milestone: Boost 1.43.0 Component: lexical_cast
Version: Boost 1.42.0 Severity: Problem
Keywords: Cc:

Description

lexical_cast issues the following warning under VC8 and higher at warning level 3:

e:\develop\libs\boost_1_42_0\boost\lexical_cast.hpp(1151) : warning C4267: 'argument' : conversion from 'size_t' to 'unsigned int', possible loss of data

The code seems to have been restructured a bit to fix ticket #3198 (or #1791), a block of disabled warnings (currently '4701' and '4702') has been introduced.

The problem can be worked-around when adding a statement to disable the warning '4267' in the same block.

Change History (4)

comment:1 by Steven Watanabe, 12 years ago

I can't reproduce the problem with VC 2010. Can you provide a test case?

comment:2 by anonymous, 12 years ago

I did a simple test with VC8 and VC10 from command line "cl.exe" like this

lex_test.cpp:


#include <...> void main() {

size_t num = 12345; std::string num_to_string = boost::lexical_cast<std::string>( num );

}


and it didn't show up, so I digged deeper and found out that the warning appears to be caused by the 64 bit warning switch /(Wp64), i.e. when you compile with

cl lex_test.cpp /I<boost_1_42_0-dir> /EHsc /W4 /Wp64

This happens with both tested VC compilers from command line, as well as in Win32 projects created with the VC8 (2005) Wizard. When using the command line, VC10 indicates the option "Wp64" as deprecated, and without the switch, it compiles without warning (as does VC8). However, all Win32 projects seem to have the switch enabled in VC8.

Not sure if there is a real 'size_t' conversion issue on 64-bit targets or if it can be ignored.

As VC reports the warning (like all problems with templates) in an ugly multi-line warning, the compile report gets quite verbose on projects which make heavy use of lexical_cast with the Wp64 option enabled when switching from e.g. boost 1.36.0 to 1.42.0.

As there is already a disabled-warning-block-for-MSVC in the lexical_cast source at this place, I escaped from the warning report hell in my private local boost copy by excluding this warning as well.

If you decide the source to be left unchanged, can you confirm there is no 64-bit issue?

comment:3 by admin@…, 12 years ago

While working on a patch today for another issue (link) in the same function in boost::lexical_cast, I came across this and decided to do some digging. I'm pretty confident that there is no actual 64-bit issue, and that this warning can be ignored safely.

From MSDN (http://msdn.microsoft.com/en-us/library/6kck0s93%28VS.80%29.aspx):

In this situation, C4267 is caused by a limitation in /Wp64 warnings. On x86, std::cout<<range_index resolves to the overload of operator<< that accepts an unsigned int, since size_t is an unsigned int on Win32. C4267 occurs because you passed a size_t as an unsigned int argument, which would cause truncation on Win64 where size_t is 64-bit, but unsigned int is still 32-bit. This can be ignored because if you compiled for Win64, std::cout<<range_index would resolve to the overload of operator<< that accepts an unsigned __int64, since that's what type size_t is on Win64. The 32-bit compiler doesn't notice, so it warns.

This warning isn't raised by std::cout, but I believe the situation described by MSDN is applies to this warning. lexical_stream_limited_src is a stream wrapper template class (derived from std::basic_streambuf), and it has an operator<< overload that accepts an unsigned int. It also has an operator<< that takes an unsigned __int64 if compiled for Win64.

Source of the issue in lexical_cast.hpp (boost 1.42):

        template< typename Target
                , typename Source
                , bool Unlimited // string representation of Source is unlimited
                , typename CharT
                >
        Target lexical_cast(
            BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
            CharT* buf, std::size_t src_len)
        {
            typedef BOOST_DEDUCED_TYPENAME
                deduce_char_traits<CharT,Target,Source>::type traits;

            typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
                lcast_streambuf_for_target<Target>::value ||
                lcast_streambuf_for_source<Source>::value
              , std::basic_streambuf<CharT>
              , lexical_streambuf_fake
              >::type base;

            BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
                Unlimited
              , detail::lexical_stream<Target,Source,traits>
              , detail::lexical_stream_limited_src<CharT,base,traits>
              >::type interpreter(buf, buf + src_len);

            Target result;
            if(!(interpreter << arg && interpreter >> result)) // line 1151, as of boost 1.42 when this issue was reported
                BOOST_LCAST_THROW_BAD_CAST(Source, Target);
            return result;
        }

Relevant declarations in lexical_stream_limited_src (boost 1.42; the full declaration starts at line 660):

        // String representation of Source has an upper limit.
        template< class CharT // a result of widest_char transformation
                , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
                , class Traits // usually char_traits<CharT>
                >
        class lexical_stream_limited_src : public Base
        {

            /* truncated */

            bool operator<<(unsigned short);
            bool operator<<(unsigned int); //
            bool operator<<(unsigned long);
#if defined(BOOST_HAS_LONG_LONG)
            bool operator<<(boost::ulong_long_type);
            bool operator<<(boost::long_long_type );
#elif defined(BOOST_HAS_MS_INT64)
            bool operator<<(unsigned __int64);
            bool operator<<(         __int64);
#endif

            /* truncated */

        }

I've submitted a patch (https://svn.boost.org/trac/boost/ticket/4334) that should resolve this. I don't have access to MSVC or a Windows machine (nor the experience for it to matter), so hopefully someone more knowledgable than me can verify if I'm correct about this being ignorable.

comment:4 by Steven Watanabe, 12 years ago

Resolution: fixed
Status: newclosed

(In [62806]) Supress MSVC /Wp64 warnings. Fixes #4184

Note: See TracTickets for help on using tickets.