Description
We've been encountering a recurring problem where testing the ranges algorithms with /analyze
will fail with fatal error C1060: compiler is out of heap space
. Specifically, the trigger seems to be constexpr
testing of ranges algorithms with /analyze
. Take P0896R4_ranges_alg_move
for example:
struct instantiator {
static constexpr int_wrapper expected_output[3] = {13, 55, 12345};
static constexpr int_wrapper expected_input[3] = {-1, -1, -1};
template <ranges::input_range Read, indirectly_writable<ranges::range_rvalue_reference_t<Read>> Write>
static constexpr void call() {
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163
#pragma warning(suppress : 4127) // conditional expression is constant
if (!ranges::contiguous_range<Read> || !is_constant_evaluated())
#endif // TRANSITION, VSO-938163
{
using ranges::move, ranges::move_result, ranges::equal, ranges::iterator_t;
{
int_wrapper input[3] = {13, 55, 12345};
int_wrapper output[3] = {-2, -2, -2};
Read wrapped_input{input};
auto result = move(wrapped_input, Write{output});
STATIC_ASSERT(same_as<decltype(result), move_result<iterator_t<Read>, Write>>);
assert(result.in == wrapped_input.end());
assert(result.out.peek() == output + 3);
assert(equal(output, expected_output));
assert(equal(input, expected_input));
}
{
int_wrapper input[3] = {13, 55, 12345};
int_wrapper output[3] = {-2, -2, -2};
Read wrapped_input{input};
auto result = move(wrapped_input.begin(), wrapped_input.end(), Write{output});
STATIC_ASSERT(same_as<decltype(result), move_result<iterator_t<Read>, Write>>);
assert(result.in == wrapped_input.end());
assert(result.out.peek() == output + 3);
assert(equal(output, expected_output));
assert(equal(input, expected_input));
}
}
}
};
int main() {
STATIC_ASSERT((test_in_write<instantiator, int_wrapper, int_wrapper>(), true)); // ***CONSTEXPR TEST***
test_in_write<instantiator, int_wrapper, int_wrapper>();
}
test_in_write<instantiator, int_wrapper, int_wrapper>()
calls instantiator::call
with 825 different combinations of template arguments to get test coverage of virtually every possible combination of range argument properties. Compiling this test with /analyze
exhausts the compiler heap resulting in C1060. It compiles fine if we comment out the // ***CONSTEXPR TEST***
line, but produces the same error if we comment out only the next non-constexpr
test line. There's no clear reason why virtually the same code should require vastly more memory to analyze when it happens to be called in a constant expression vs. not. Indeed it's not clear to me why that distinction would affect the static analyzer at all.
We'll work around this for the time being by conditionally compiling the constexpr
test only when _PREFAST_
is not defined, which indicates that /analyze
is not enabled. @CaseyCarter will try to reduce a simpler test case and submit a static analyzer bug on Developer Community.