none
warning C4267 with std::vector

    Question

  • I get strange warnings using Visual Studio 2005 in the following simple program:

     

    WarningTest.cpp

    Code Snippet

    #include <vector>
    #include <map>

    int main()
    {
       std::map<unsigned, int> m;
       std::vector<size_t> v(1, 0);
    }

     

    Command Lines

    Code Snippet
    Creating temporary file "c:\Documents and Settings\Anders\My Documents\Visual Studio 2005\Projects\WarningTest\WarningTest\Debug\RSP00003434482004.rsp" with contents
    [
    /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc80.pdb" /W4 /c /Wp64 /ZI /TP ".\WarningTest.cpp"
    ]
    Creating command line "cl.exe @"c:\Documents and Settings\Anders\My Documents\Visual Studio 2005\Projects\WarningTest\WarningTest\Debug\RSP00003434482004.rsp" /nologo"

     

    Output Window

    Code Snippet
    Compiling...
    WarningTest.cpp
    c:\program files\microsoft visual studio 8\vc\include\xutility(2988) : warning C4267: '=' : conversion from 'size_t' to 'unsigned int', possible loss of data
            c:\program files\microsoft visual studio 8\vc\include\xutility(3044) : see reference to function template instantiation 'void std::_Fill_n(_OutIt,_Diff,const _Ty &,std::_Range_checked_iterator_tag)' being compiled
            with
            [
                _Diff=__w64 unsigned int,
                _Ty=size_t,
                _OutIt=unsigned int *
            ]
            c:\program files\microsoft visual studio 8\vc\include\xutility(3524) : see reference to function template instantiation 'void std::_Fill_n<_OutIt,_Diff,_Ty>(_OutIt,_Diff,const _Ty &,std::random_access_iterator_tag,std::_Range_checked_iterator_tag)' being compiled
            with
            [
                _OutIt=unsigned int *,
                _Diff=__w64 unsigned int,
                _Ty=size_t
            ]
            c:\program files\microsoft visual studio 8\vc\include\memory(416) : see reference to function template instantiation 'void stdext::unchecked_fill_n<_FwdIt,_Diff,_Tval>(_OutIt,_Diff,const _Ty &)' being compiled
            with
            [
                _FwdIt=unsigned int *,
                _Diff=__w64 unsigned int,
                _Tval=size_t,
                _OutIt=unsigned int *,
                _Ty=size_t
            ]
            c:\program files\microsoft visual studio 8\vc\include\memory(916) : see reference to function template instantiation 'void std::_Uninit_fill_n<_FwdIt,_Diff,_Tval,_Alloc>(_FwdIt,_Diff,const _Tval &,_Alloc &,std::_Scalar_ptr_iterator_tag,std::_Range_checked_iterator_tag)' being compiled
            with
            [
                _FwdIt=unsigned int *,
                _Diff=__w64 unsigned int,
                _Tval=size_t,
                _Alloc=std::allocator
            ]
            c:\program files\microsoft visual studio 8\vc\include\vector(1208) : see reference to function template instantiation 'void stdext::unchecked_uninitialized_fill_n>(_FwdIt,_Diff,const _Tval &,_Alloc &)' being compiled
            with
            [
                _Ty=size_t,
                _FwdIt=unsigned int *,
                _Diff=__w64 unsigned int,
                _Tval=size_t,
                _Alloc=std::allocator
            ]
            c:\program files\microsoft visual studio 8\vc\include\vector(1207) : while compiling class template member function 'unsigned int *std::vector<_Ty>::_Ufill(unsigned int *,__w64 unsigned int,const _Ty &)'
            with
            [
                _Ty=size_t
            ]
            c:\documents and settings\anders\my documents\visual studio 2005\projects\warningtest\warningtest\warningtest.cpp(7) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
            with
            [
                _Ty=size_t
            ]

     

    It seems like the incorrect allocator is instantiated.

     

    Regards,

    Anders

    Wednesday, March 05, 2008 8:31 PM

Answers

  • It's worth noting that in VS2008, /Wp64 is deprecated for this very reason -- too many incorrect and missing warnings. If you really want 64-bit compatibility warnings, compile your code with a 64-bit cross-compiler.

     

    From a post by Stephan T. Lavavej [MSFT]:

    "/Wp64 was added a long time ago, when we had only the 32-bit compiler, so that developers could begin scanning their code for 64-bit portability issues and prevent new ones from creeping in with new code.  This was a nice idea.  However, /Wp64 had problems.  In particular, it suffers from false negatives (true problems not detected), and even worse, false positives (warning about perfectly correct code).  Perhaps worst of all, /Wp64 interacts extremely badly with templates.

     

    The problem is that /Wp64 is kind of part of the type system, but kind of not.  In particular, the __w64 qualifier does not produce separate template instantiations.  That is, in 32-bit, vector<__w64 unsigned int> (aka vector<size_t>) and vector<unsigned int> refer to the same instantiation.  You can detect this through explicit specializations.  This is bad, because there are some cases we want /Wp64 warnings to fire, and some cases we don't:

     

    vector<size_t> vs; // Filled with some elements (not shown)

    vector<unsigned int> vi; // Also filled with some elements (not shown)

    size_t s; // Initialized to some value (not shown)

    unsigned int i; // Also initialized to some value (not shown)

    vs[0] = s; // Should not warn

    vs[0] = i; // Should not warn

    vi[0] = s; // Should warn

    vi[0] = i; // Should not warn

    s = vs[0]; // Should not warn

    i = vs[0]; // Should warn

    s = vi[0]; // Should not warn

    i = vi[0]; // Should not warn

     

    Since we have only one template instantation, we cannot possibly get all the cases correct - the instantiation has to be stamped with either "expands to 64-bit on 64-bit systems" or "doesn't expand", and either way gets some cases wrong.  This is bad enough, but it turns out that the way the compiler selects what to stamp the instantation with is extremely confusing - it chooses the first instantiation that it sees.  This leads to almost incomprehensible /Wp64 warnings with no easy workarounds.

     

    The actual 64-bit compiler suffers none of these problems - no false negatives, no false positives, and no crazy interactions with templates.  Since we now have a 32-to-64-bit cross-compiler, there is absolutely no purpose for /Wp64.  That is why we have deprecated it in Orcas and will rip it out in Orcas + 1 (hopefully)."

    Friday, March 07, 2008 10:05 PM

All replies

  • This is due to the presense of /Wp64 in your project options - it's a potential 64-bit portability warning that you can safely ignore.

     

     

    Wednesday, March 05, 2008 10:30 PM
  • It should not trigger this potential 64-bit portability warning.

    It is the line with std::vector<size_t> that triggers the warning.

    std::vector<size_t> is expanded to std::vector<size_t, std::allocator<size_t>>.

    std::allocator<size_t> should have the pointer and const_pointer typedefs to be size_t* and const size_t*, and not unsigned* and const unsigned* as it is in my example.
    Thursday, March 06, 2008 10:19 AM
  • Absolutely true.  The fact remains that it's a harmless 64-bit portability warning that you can safely ignore, or remove /Wp64 from your options if you don't want to see it.

     

    Friday, March 07, 2008 9:53 PM
  • It's worth noting that in VS2008, /Wp64 is deprecated for this very reason -- too many incorrect and missing warnings. If you really want 64-bit compatibility warnings, compile your code with a 64-bit cross-compiler.

     

    From a post by Stephan T. Lavavej [MSFT]:

    "/Wp64 was added a long time ago, when we had only the 32-bit compiler, so that developers could begin scanning their code for 64-bit portability issues and prevent new ones from creeping in with new code.  This was a nice idea.  However, /Wp64 had problems.  In particular, it suffers from false negatives (true problems not detected), and even worse, false positives (warning about perfectly correct code).  Perhaps worst of all, /Wp64 interacts extremely badly with templates.

     

    The problem is that /Wp64 is kind of part of the type system, but kind of not.  In particular, the __w64 qualifier does not produce separate template instantiations.  That is, in 32-bit, vector<__w64 unsigned int> (aka vector<size_t>) and vector<unsigned int> refer to the same instantiation.  You can detect this through explicit specializations.  This is bad, because there are some cases we want /Wp64 warnings to fire, and some cases we don't:

     

    vector<size_t> vs; // Filled with some elements (not shown)

    vector<unsigned int> vi; // Also filled with some elements (not shown)

    size_t s; // Initialized to some value (not shown)

    unsigned int i; // Also initialized to some value (not shown)

    vs[0] = s; // Should not warn

    vs[0] = i; // Should not warn

    vi[0] = s; // Should warn

    vi[0] = i; // Should not warn

    s = vs[0]; // Should not warn

    i = vs[0]; // Should warn

    s = vi[0]; // Should not warn

    i = vi[0]; // Should not warn

     

    Since we have only one template instantation, we cannot possibly get all the cases correct - the instantiation has to be stamped with either "expands to 64-bit on 64-bit systems" or "doesn't expand", and either way gets some cases wrong.  This is bad enough, but it turns out that the way the compiler selects what to stamp the instantation with is extremely confusing - it chooses the first instantiation that it sees.  This leads to almost incomprehensible /Wp64 warnings with no easy workarounds.

     

    The actual 64-bit compiler suffers none of these problems - no false negatives, no false positives, and no crazy interactions with templates.  Since we now have a 32-to-64-bit cross-compiler, there is absolutely no purpose for /Wp64.  That is why we have deprecated it in Orcas and will rip it out in Orcas + 1 (hopefully)."

    Friday, March 07, 2008 10:05 PM
  • Thank you ildjarn for that very informative post.

    Regards,
    Anders
    Friday, March 07, 2008 10:39 PM