C++20 Compiler Error in Visual Studio 2022 Community: Resolving Internal Error C1001

1.1k Views Asked by At

I am facing an issue with C++20 in Visual Studio 2022 Community. The code works correctly in G++ but I get an internal compiler error with MSVC.

Here is the code:

#include <iostream>

struct Foo {
    float* data;

    Foo(float * const * const & address) :
        data(*address)
    {}

    Foo(float ** const && address) :
        data(*address)
    {}
};

int main() {
    int64_t size = 12;

    float* data = new float[size];
    float** address = &data;

    auto foo = Foo(std::move(address));
}

Error:

Build started...
1>------ Build started: Project: ConsoleApplication4, Configuration: Debug x64 ------
1>Scanning sources for module dependencies...
1>main.cpp
1>main.cpp(26,35): fatal  error C1001: Internal compiler error.
1>(compiler file 'msc1.cpp', line 1584)
1> To work around this problem, try simplifying or changing the program near the locations listed above.
1>If possible please provide a repro here: https://developercommunity.visualstudio.com
1>Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
1>INTERNAL COMPILER ERROR in 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\bin\HostX64\x64\CL.exe'
1>    Please choose the Technical Support command on the Visual C++
1>    Help menu, or open the Technical Support help file for more information
1>Done building project "ConsoleApplication4.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
========== Build started at 4:08 PM and took 01.716 seconds ==========

The error code is C1001, which suggests simplifying or changing the program. However, another project requires being able to differentiate between l-value and r-value pointers in a similar way. I would appreciate any assistance in resolving this issue.

1

There are 1 best solutions below

0
Adrian Mole On BEST ANSWER

Generally speaking, internal compiler errors aren't something that anyone outside the MSVC development team can really address, and the problem should be reported to that team.

However, as a "quick fix", we can note that std::move(x) is equivalent to an appropriate static_cast<T&&>(x); from cppreference (bold emphasis mine):

In particular, std::move produces an xvalue expression that identifies its argument t. It is exactly equivalent to a static_cast to an rvalue reference type.

Thus, simply changing your std::move call to an equivalent cast makes MSVC happy:

int main()
{
    size_t size = 12; // Changed to "size_t" to be more correct!

    float* data = new float[size];
    float** address = &data;

//  auto foo = Foo(std::move(address)); // fatal error C1001: Internal compiler error
    auto foo = Foo(static_cast<float** const&&>(address)); // MSVC happy and uses "rvalue c'tor"
}

Looking at this in more detail, I notice that the MSVC implementation of std::move<T> returns what a static_cast like the above yields, using the type that std::remove_reference<T>::type yields as the 'base type' for that cast. Here is the definition from the <type_traits> header:

_EXPORT_STD template <class _Ty>
_NODISCARD _MSVC_INTRINSIC constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) noexcept {
    return static_cast<remove_reference_t<_Ty>&&>(_Arg);
}

What seems to be confusing the compiler here is the lack of a const qualifier on the address variable. Adding that also makes MSVC happy:

int main()
{
    size_t size = 12; // Changed to "size_t" to be more correct!

    float* data = new float[size];
    float** const address = &data; // Added the "const" qualifier here ...

    auto foo = Foo(std::move(address)); // ... and now MSVC is happy!
}