The just released VC++14 has a problem with the boost::mpl::size_t template. After preprocessing it sees: namespace boost { namespace mpl { template< std::size_t N > struct size_t { static const std::size_t value = N; typedef size_t type; typedef std::size_t value_type; typedef integral_c_tag tag; typedef boost::mpl::size_t< static_caststd::size_t((value + 1)) > next; typedef boost::mpl::size_t< static_caststd::size_t((value - 1)) > prior; operator std::size_t() const { return static_caststd::size_t(this->value); } }; template< std::size_t N > std::size_t const boost::mpl::size_t< N >::value; }} and gives the error message: size_t.cpp(nnn): error C2872: 'size_t': ambiguous symbol predefined C++ types (compiler internal)(16): note: could be 'unsigned int size_t' size_t.cpp(nnn): note: or 'boost::mpl::size_t' pointing to the line after it encounters 'struct size_t' as far as I can make out ( you need to preprocess the size_t.cpp test, comment out the #line directives and run the test against the preprocessed result to see what the compiler is objecting to ). It therefore fails a number of mpl tests which all prior versions of VC++ pass. It flags this error in 5 mpl tests which use the boost::mpl::size_t integral wrapper, among which the easiest to analyze is the size_t.cpp test itself. Anybody have any idea what is going on here with the compiler, or whether it can be fixed somehow in VC++14 for the mpl code ?
On Fri, Jul 24, 2015 at 7:41 PM, Edward Diener
pointing to the line after it encounters 'struct size_t' as far as I can make out ( you need to preprocess the size_t.cpp test, comment out the #line directives and run the test against the preprocessed result to see what the compiler is objecting to ). It therefore fails a number of mpl tests which all prior versions of VC++ pass.
It flags this error in 5 mpl tests which use the boost::mpl::size_t integral wrapper, among which the easiest to analyze is the size_t.cpp test itself.
Anybody have any idea what is going on here with the compiler, or whether it can be fixed somehow in VC++14 for the mpl code ?
I don't have the compiler, but my guess is it's probably actually confused on the line: typedef size_t type; A simple workaround to try could be to change the typedef to: typedef mpl::size_t<N> type; If that fix works, I'd be surprised if such a change would break any other compilers. This is all just a guess, though. -- -Matt Calabrese
On 7/25/2015 2:48 AM, Matt Calabrese wrote:
On Fri, Jul 24, 2015 at 7:41 PM, Edward Diener
wrote: pointing to the line after it encounters 'struct size_t' as far as I can make out ( you need to preprocess the size_t.cpp test, comment out the #line directives and run the test against the preprocessed result to see what the compiler is objecting to ). It therefore fails a number of mpl tests which all prior versions of VC++ pass.
It flags this error in 5 mpl tests which use the boost::mpl::size_t integral wrapper, among which the easiest to analyze is the size_t.cpp test itself.
Anybody have any idea what is going on here with the compiler, or whether it can be fixed somehow in VC++14 for the mpl code ?
I don't have the compiler, but my guess is it's probably actually confused on the line:
typedef size_t type;
A simple workaround to try could be to change the typedef to:
typedef mpl::size_t<N> type;
If that fix works, I'd be surprised if such a change would break any other compilers. This is all just a guess, though.
Unfortunately that does not fix the problem. It appears that VC++14 thinks that the designation: namespace boost { namespace mpl { template< std::size_t N > struct size_t is ambiguous because somehow it has determined that 'size_t' is a predefined C++ type, like 'int', and therefore cannot be used altogether. What a compiler regression ! If I can get all the #line directives and empty lines out of the preprocess source I will report it to Microsoft. It is just a really bad failure of the just-released VC++14 compiler. I am a bit surprised that the VC++ developers did not try to run the compiler against some of the key Boost libraries, like MPL, just to get out the kinks, before they released the product. As is VC++14 is broken with any library that uses the boost::mpl::size_t integral wrapper for std::size_t. The only workaround I can think of is to change the name for VC++14 to something like boost::mpl::size_t_.
On 7/25/2015 2:48 AM, Matt Calabrese wrote:
On Fri, Jul 24, 2015 at 7:41 PM, Edward Diener
wrote: pointing to the line after it encounters 'struct size_t' as far as I can make out ( you need to preprocess the size_t.cpp test, comment out the #line directives and run the test against the preprocessed result to see what the compiler is objecting to ). It therefore fails a number of mpl tests which all prior versions of VC++ pass.
It flags this error in 5 mpl tests which use the boost::mpl::size_t integral wrapper, among which the easiest to analyze is the size_t.cpp test itself.
Anybody have any idea what is going on here with the compiler, or whether it can be fixed somehow in VC++14 for the mpl code ?
I don't have the compiler, but my guess is it's probably actually confused on the line:
typedef size_t type;
A simple workaround to try could be to change the typedef to:
typedef mpl::size_t<N> type;
If that fix works, I'd be surprised if such a change would break any other compilers. This is all just a guess, though.
Actually this program, which is what the boost::mpl::size_t outputs as in VC++14, compiles without error in VC++14: #include <cstddef> namespace boost { namespace mpl { struct integral_c_tag { static const int value = 0; }; template< std::size_t N > struct size_t { static const std::size_t value = N; typedef size_t type; typedef std::size_t value_type; typedef integral_c_tag tag; typedef boost::mpl::size_t< static_caststd::size_t((value + 1)) > next; typedef boost::mpl::size_t< static_caststd::size_t((value - 1)) > prior; operator std::size_t() const { return static_caststd::size_t(this->value); } }; template< std::size_t N > std::size_t const boost::mpl::size_t< N >::value; }} int main() { return 0; } So why the MPL tests which use boost::mpl::size_t are failing is still a mystery to me. When the error message shows in the size_t test it says: size_t.cpp(30): error C2872: 'size_t': ambiguous symbol predefined C++ types (compiler internal)(16): note: could be 'unsigned int size_t' C:\Programming\VersionControl\modular-boost\boost/mpl/aux_/integral_wrapper.hpp(44): note: or 'boost::mpl::size_t' but the first line of the error message is pointing to the last empty line of size_t.cpp. If I preprocess the file and then test the preprocessed file, the error message is: size_t_ii.cpp(68259): error C2872: 'size_t': ambiguous symbol predefined C++ types (compiler internal)(16): note: could be 'unsigned int size_t' size_t_ii.cpp(16566): note: or 'boost::mpl::size_t' but here the first line of the error message is pointing to one beyond the last line of the preprocessed file.
On 7/25/2015 2:48 AM, Matt Calabrese wrote:
On Fri, Jul 24, 2015 at 7:41 PM, Edward Diener
wrote: pointing to the line after it encounters 'struct size_t' as far as I can make out ( you need to preprocess the size_t.cpp test, comment out the #line directives and run the test against the preprocessed result to see what the compiler is objecting to ). It therefore fails a number of mpl tests which all prior versions of VC++ pass.
It flags this error in 5 mpl tests which use the boost::mpl::size_t integral wrapper, among which the easiest to analyze is the size_t.cpp test itself.
Anybody have any idea what is going on here with the compiler, or whether it can be fixed somehow in VC++14 for the mpl code ?
I don't have the compiler, but my guess is it's probably actually confused on the line:
typedef size_t type;
A simple workaround to try could be to change the typedef to:
typedef mpl::size_t<N> type;
If that fix works, I'd be surprised if such a change would break any other compilers. This is all just a guess, though.
My latest investigation, using the mpl::size_t code directly in a test,
shows that:
// size_t_bug.cpp
#include <cstddef>
namespace boost { namespace mpl {
struct integral_c_tag { static const int value = 0; };
template< std::size_t N >
struct size_t
{
static const std::size_t value = N;
typedef size_t type;
typedef std::size_t value_type;
typedef integral_c_tag tag;
typedef boost::mpl::size_t< static_caststd::size_t((value + 1)) >
next;
typedef boost::mpl::size_t< static_caststd::size_t((value - 1)) >
prior;
operator std::size_t() const { return
static_caststd::size_t(this->value); }
};
template< std::size_t N >
std::size_t const boost::mpl::size_t< N >::value;
}}
#include
On 26.07.2015 17:20, Edward Diener wrote:
On 7/25/2015 2:48 AM, Matt Calabrese wrote:
On Fri, Jul 24, 2015 at 7:41 PM, Edward Diener
wrote: pointing to the line after it encounters 'struct size_t' as far as I can make out ( you need to preprocess the size_t.cpp test, comment out the #line directives and run the test against the preprocessed result to see what the compiler is objecting to ). It therefore fails a number of mpl tests which all prior versions of VC++ pass.
It flags this error in 5 mpl tests which use the boost::mpl::size_t integral wrapper, among which the easiest to analyze is the size_t.cpp test itself.
Anybody have any idea what is going on here with the compiler, or whether it can be fixed somehow in VC++14 for the mpl code ?
I don't have the compiler, but my guess is it's probably actually confused on the line:
typedef size_t type;
A simple workaround to try could be to change the typedef to:
typedef mpl::size_t<N> type;
If that fix works, I'd be surprised if such a change would break any other compilers. This is all just a guess, though.
My latest investigation, using the mpl::size_t code directly in a test, shows that:
// size_t_bug.cpp
#include <cstddef> namespace boost { namespace mpl { struct integral_c_tag { static const int value = 0; }; template< std::size_t N > struct size_t { static const std::size_t value = N; typedef size_t type; typedef std::size_t value_type; typedef integral_c_tag tag; typedef boost::mpl::size_t< static_caststd::size_t((value + 1)) > next; typedef boost::mpl::size_t< static_caststd::size_t((value - 1)) > prior; operator std::size_t() const { return static_caststd::size_t(this->value); } }; template< std::size_t N > std::size_t const boost::mpl::size_t< N >::value; }}
#include
int main() { return 0; } using namespace boost; using namespace mpl; fails under VC++14 with:
size_t_bug.cpp(26): error C2872: 'size_t': ambiguous symbol predefined C++ types (compiler internal)(16): note: could be 'unsigned int size_t' size_t_bug.cpp(6): note: or 'boost::mpl::size_t'
but if I comment out the include of lightweight test or if I comment out the using directive, the source compiles without error. How using directives which occur after all code can affect the compilation is beyond me.
Anybody who would like to pitch in and try to determine what is causing VC++14 to fail with the above code, which is essentially why it is failing with the MPL tests involving boost::mpl::size_t, please feel free to do so.
Needless to say VC++12 and below, as well as gcc and clang, compile the test without error.
This is obviously a compiler bug. Could you report it to MS Connect? If you're still interested in experimenting, you could try reducing it further by, e.g. replacing lightweight_test.hpp with bits of code from it, starting from just header includes from lightweight_test.hpp.
On 7/26/2015 10:34 AM, Andrey Semashev wrote:
On 26.07.2015 17:20, Edward Diener wrote:
On 7/25/2015 2:48 AM, Matt Calabrese wrote:
On Fri, Jul 24, 2015 at 7:41 PM, Edward Diener
wrote: pointing to the line after it encounters 'struct size_t' as far as I can make out ( you need to preprocess the size_t.cpp test, comment out the #line directives and run the test against the preprocessed result to see what the compiler is objecting to ). It therefore fails a number of mpl tests which all prior versions of VC++ pass.
It flags this error in 5 mpl tests which use the boost::mpl::size_t integral wrapper, among which the easiest to analyze is the size_t.cpp test itself.
Anybody have any idea what is going on here with the compiler, or whether it can be fixed somehow in VC++14 for the mpl code ?
I don't have the compiler, but my guess is it's probably actually confused on the line:
typedef size_t type;
A simple workaround to try could be to change the typedef to:
typedef mpl::size_t<N> type;
If that fix works, I'd be surprised if such a change would break any other compilers. This is all just a guess, though.
My latest investigation, using the mpl::size_t code directly in a test, shows that:
// size_t_bug.cpp
#include <cstddef> namespace boost { namespace mpl { struct integral_c_tag { static const int value = 0; }; template< std::size_t N > struct size_t { static const std::size_t value = N; typedef size_t type; typedef std::size_t value_type; typedef integral_c_tag tag; typedef boost::mpl::size_t< static_caststd::size_t((value + 1)) > next; typedef boost::mpl::size_t< static_caststd::size_t((value - 1)) > prior; operator std::size_t() const { return static_caststd::size_t(this->value); } }; template< std::size_t N > std::size_t const boost::mpl::size_t< N >::value; }}
#include
int main() { return 0; } using namespace boost; using namespace mpl; fails under VC++14 with:
size_t_bug.cpp(26): error C2872: 'size_t': ambiguous symbol predefined C++ types (compiler internal)(16): note: could be 'unsigned int size_t' size_t_bug.cpp(6): note: or 'boost::mpl::size_t'
but if I comment out the include of lightweight test or if I comment out the using directive, the source compiles without error. How using directives which occur after all code can affect the compilation is beyond me.
Anybody who would like to pitch in and try to determine what is causing VC++14 to fail with the above code, which is essentially why it is failing with the MPL tests involving boost::mpl::size_t, please feel free to do so.
Needless to say VC++12 and below, as well as gcc and clang, compile the test without error.
This is obviously a compiler bug. Could you report it to MS Connect?
If you're still interested in experimenting, you could try reducing it further by, e.g. replacing lightweight_test.hpp with bits of code from it, starting from just header includes from lightweight_test.hpp.
Exactly what I intended to do. My experience with MS Connect is that unless I can reduce code to something which does not include any non-VC++ or non-Windows header they cannot figure out anything or take the bug report seriously.
On 2015-07-26 10:40, Edward Diener wrote: <snip>
Exactly what I intended to do. My experience with MS Connect is that unless I can reduce code to something which does not include any non-VC++ or non-Windows header they cannot figure out anything or take the bug report seriously.
I'm not sure how easy it is to use with MSVC, but don't forget multidelta: http://delta.tigris.org/ John Bytheway
On 7/26/2015 11:02 AM, John Bytheway wrote:
On 2015-07-26 10:40, Edward Diener wrote: <snip>
Exactly what I intended to do. My experience with MS Connect is that unless I can reduce code to something which does not include any non-VC++ or non-Windows header they cannot figure out anything or take the bug report seriously.
I'm not sure how easy it is to use with MSVC, but don't forget multidelta: http://delta.tigris.org/
Thanks for the link.
Andrey Semashev wrote:
On 26.07.2015 17:20, Edward Diener wrote:
...
but if I comment out the include of lightweight test or if I comment out the using directive, the source compiles without error.
...
If you're still interested in experimenting, you could try reducing it further by, e.g. replacing lightweight_test.hpp with bits of code from it, starting from just header includes from lightweight_test.hpp.
My money is on #include
On 7/26/2015 11:00 AM, Peter Dimov wrote:
My money is on #include
, because lightweight_test.hpp doesn't do much else involving size_t. Or perhaps it's the #include <iostream> that pulls something in? It's <iostream>. Which is better as now the bug report is self-contained. :-)
Yes. #include <cstddef> #include <iostream> namespace boost { namespace mpl { struct integral_c_tag { static const int value = 0; }; template< std::size_t N > struct size_t { static const std::size_t value = N; typedef size_t type; typedef std::size_t value_type; typedef integral_c_tag tag; typedef boost::mpl::size_t< static_caststd::size_t((value + 1)) > next; typedef boost::mpl::size_t< static_caststd::size_t((value - 1)) > prior; operator std::size_t() const { return static_caststd::size_t(this->value); } }; template< std::size_t N > std::size_t const boost::mpl::size_t< N >::value; }} int main() { return 0; } using namespace boost; using namespace mpl; The above fails, nor does the order of the two #includes affect anything. Removing the using directives at the end and it succeeds. I will report this directly to Microsoft. Maybe STL can get them to address this bug. The code is a much simplified version of the MPL tests using boost::mpl::size_t.
On 26/07/2015 16:16, Edward Diener wrote:
#include <cstddef> #include <iostream> namespace boost { namespace mpl { struct integral_c_tag { static const int value = 0; }; template< std::size_t N > struct size_t { static const std::size_t value = N; typedef size_t type; typedef std::size_t value_type; typedef integral_c_tag tag; typedef boost::mpl::size_t< static_caststd::size_t((value + 1))
next; typedef boost::mpl::size_t< static_caststd::size_t((value - 1)) prior; operator std::size_t() const { return static_caststd::size_t(this->value); } }; template< std::size_t N > std::size_t const boost::mpl::size_t< N >::value; }}
int main() { return 0; } using namespace boost; using namespace mpl;
That builds in release mode, but not debug, weird! John.
On 7/27/2015 6:28 AM, John Maddock wrote:
On 26/07/2015 16:16, Edward Diener wrote:
#include <cstddef> #include <iostream> namespace boost { namespace mpl { struct integral_c_tag { static const int value = 0; }; template< std::size_t N > struct size_t { static const std::size_t value = N; typedef size_t type; typedef std::size_t value_type; typedef integral_c_tag tag; typedef boost::mpl::size_t< static_caststd::size_t((value + 1))
next; typedef boost::mpl::size_t< static_caststd::size_t((value - 1)) prior; operator std::size_t() const { return static_caststd::size_t(this->value); } }; template< std::size_t N > std::size_t const boost::mpl::size_t< N >::value; }}
int main() { return 0; } using namespace boost; using namespace mpl;
That builds in release mode, but not debug, weird!
What are the different options between release and debug mode ?
On 27-07-2015 12:56, Edward Diener wrote:
On 7/27/2015 6:28 AM, John Maddock wrote:
That builds in release mode, but not debug, weird!
What are the different options between release and debug mode ?
I've tracked the issue down to the `xlocale` header, where the `_Crt_new_delete` class definition depends on the `_DEBUG` flag. A minimal example for reproduction, based on it, follows: struct B { #ifdef _DEBUG void operator delete(void *) {} #endif }; struct S : B { virtual ~S() {} }; namespace boost { namespace mpl { struct size_t {}; } } int main() { return 0; } using namespace boost::mpl;
On 7/27/2015 1:44 PM, Samuel Neves wrote:
On 27-07-2015 12:56, Edward Diener wrote:
On 7/27/2015 6:28 AM, John Maddock wrote:
That builds in release mode, but not debug, weird!
What are the different options between release and debug mode ?
To answer my own question compiling with /MDd turns on debug ( and the define of _DEBUG ) whereas just /MD is for release.
I've tracked the issue down to the `xlocale` header, where the `_Crt_new_delete` class definition depends on the `_DEBUG` flag. A minimal example for reproduction, based on it, follows:
struct B { #ifdef _DEBUG void operator delete(void *) {} #endif };
struct S : B { virtual ~S() {} };
namespace boost { namespace mpl { struct size_t {}; } }
int main() { return 0; }
using namespace boost::mpl;
I have verified that you are correct. Can you post what you have found on the bug report page at https://connect.microsoft.com/VisualStudio/feedback/details/1593471/compile-... ? It might help although STL has already said that a Microsoft employee is working on a fix, which implies that they probably already know what is causing the problem.
On 7/26/2015 11:00 AM, Peter Dimov wrote:
My money is on #include
, because lightweight_test.hpp doesn't do much else involving size_t. Or perhaps it's the #include <iostream> that pulls something in? It's <iostream>. Which is better as now the bug report is self-contained. :-)
I submitted the bug to MS Connect. The bug number is 1593471 and the web page for the bug report is: https://connect.microsoft.com/VisualStudio/feedback/details/1593471/compile-....
Edward Diener writes:
I submitted the bug to MS Connect. The bug number is 1593471 and the web page for the bug report is:
https://connect.microsoft.com/VisualStudio/feedback/details/1593471/
Thank you for the link. It's worth noting that the supplied code compiles cleanly with compiler v19.00.23106.0 (the version presently on http://webcompiler.cloudapp.net/), so it's quite possible that this is already fixed for Update 1. Regards,
On 7/27/2015 4:40 AM, Adam Merz wrote:
Edward Diener writes:
I submitted the bug to MS Connect. The bug number is 1593471 and the web page for the bug report is:
https://connect.microsoft.com/VisualStudio/feedback/details/1593471/
Thank you for the link.
It's worth noting that the supplied code compiles cleanly with compiler v19.00.23106.0 (the version presently on http://webcompiler.cloudapp.net/), so it's quite possible that this is already fixed for Update 1.
When I tried it at http://webcompiler.cloudapp.net/ with the compiler options I give in the bug report it failed in the same way as the bug report.
[Edward Diener]
I submitted the bug to MS Connect. The bug number is 1593471
Thanks, JonCaves is testing a fix now.
My experience with MS Connect is that unless I can reduce code to something which does not include any non-VC++ or non-Windows header they cannot figure out anything or take the bug report seriously.
Self-contained repros that avoid dragging in third-party code have at least two major benefits: they are more likely to be real bugs in the toolset, and they are significantly easier to investigate. When I report compiler bugs (and due to the nature of my work, I file something like 150 per year), I try to reduce them all the way down to library-free repros, so the compiler devs don't need to dig through vast amounts of STL internals that they don't understand as thoroughly as I do. Reducing repros takes some time, but it's usually not very hard - I just have to throw away irrelevant code, but it's code that I'm familiar with, so I know how to chop it down. And in return, I get fixes quite rapidly. We don't expect customers to be able to reduce repros all the way down to library-free, but if you can chop out Boost, that really helps. (For ICEs, preprocessed repros are usually sufficient, although smaller is always better.) STL
On 7/27/2015 3:29 PM, Stephan T. Lavavej wrote:
[Edward Diener]
I submitted the bug to MS Connect. The bug number is 1593471
Thanks, JonCaves is testing a fix now.
Glad to hear it.
My experience with MS Connect is that unless I can reduce code to something which does not include any non-VC++ or non-Windows header they cannot figure out anything or take the bug report seriously.
Self-contained repros that avoid dragging in third-party code have at least two major benefits: they are more likely to be real bugs in the toolset, and they are significantly easier to investigate.
When I report compiler bugs (and due to the nature of my work, I file something like 150 per year), I try to reduce them all the way down to library-free repros, so the compiler devs don't need to dig through vast amounts of STL internals that they don't understand as thoroughly as I do. Reducing repros takes some time, but it's usually not very hard - I just have to throw away irrelevant code, but it's code that I'm familiar with, so I know how to chop it down. And in return, I get fixes quite rapidly. We don't expect customers to be able to reduce repros all the way down to library-free, but if you can chop out Boost, that really helps.
(For ICEs, preprocessed repros are usually sufficient, although smaller is always better.)
I did reduce the original problem to code and VC++ headers to make it easier to fix.
On 7/26/2015 11:00 AM, Peter Dimov wrote:
My money is on #include
, because lightweight_test.hpp doesn't do much else involving size_t. Or perhaps it's the #include <iostream> that pulls something in? It's <iostream>. Which is better as now the bug report is self-contained. :-)
I have created a branch for MPL called 'vc14_tests_fix' at https://github.com/boostorg/mpl.git, based on MPL 'develop', which fixes the failed VC++14 MPL tests. Of course the VC++14 bug is just being masked by this fix. I will let others decide on whether we want to update our MPL tests on 'develop' based on this test fix.
participants (9)
-
Adam Merz
-
Andrey Semashev
-
Edward Diener
-
John Bytheway
-
John Maddock
-
Matt Calabrese
-
Peter Dimov
-
Samuel Neves
-
Stephan T. Lavavej