Additional instantiations of anonymous enum inside a template

Hello cfe-dev group,

Consider this template metaprogram:
template struct fib { enum { value = fib::value + fib::value}; };

template <> struct fib<1> { enum { value = 1 }; };
template <> struct fib<0> { enum { value = 0 }; };

During compilation of ‘fib<2>::value’ (after finally getting memoized result of instantiation of struct fib<0>) Clang «instantiates the anonymous enum inside fib<0> and fib<1>» 129 times in sum. In case, when we use ‘constexpr static auto’ instead of ‘enum’, no additional instantiations occurs. Why Clang performs additional instantiations in the first case?

Thank you,
Pavel

Hello cfe-dev group,

Consider this template metaprogram:
template <unsigned N> struct fib { enum { value = fib<N-1>::value +
fib<N-2>::value}; };
template <> struct fib<1> { enum { value = 1 }; };
template <> struct fib<0> { enum { value = 0 }; };

During compilation of 'fib<2>::value' (after finally getting memoized
result of instantiation of struct fib<0>) Clang «instantiates the anonymous
enum inside fib<0> and fib<1>» 129 times in sum.

That sounds like a bug. How are you observing it?

In case, when we use 'constexpr static auto' instead of 'enum', no

Hello cfe-dev group,

Consider this template metaprogram:
template <unsigned N> struct fib { enum { value = fib<N-1>::value +
fib<N-2>::value}; };
template <> struct fib<1> { enum { value = 1 }; };
template <> struct fib<0> { enum { value = 0 }; };

During compilation of 'fib<2>::value' (after finally getting memoized
result of instantiation of struct fib<0>) Clang «instantiates the anonymous
enum inside fib<0> and fib<1>» 129 times in sum.

That sounds like a bug. How are you observing it?

I debugged the metaprogram with use of Metashell tool.

Hello cfe-dev group,

Consider this template metaprogram:
template struct fib { enum { value = fib::value + fib::value}; };
template <> struct fib<1> { enum { value = 1 }; };
template <> struct fib<0> { enum { value = 0 }; };

During compilation of ‘fib<2>::value’ (after finally getting memoized result of instantiation of struct fib<0>) Clang «instantiates the anonymous enum inside fib<0> and fib<1>» 129 times in sum.

That sounds like a bug. How are you observing it?

I debugged the metaprogram with use of Metashell tool.

Possibly this is a bug in metashell? How does it get this information?

Hi,

I’m one of the developers of Metashell (https://github.com/sabel83/metashell), more specifically the developer of metadebugger, which was used to reproduce this issue.

Metashell uses Templight (http://plc.inf.elte.hu/templight/) to gather information about the template instantiations.

I put together a small test which reproduces the issue without Metashell, using only a clang patched with Templight:
https://gist.github.com/r0mai/4d90fdc8007af96c2dd1

You can find the trace that Templight produced in the gist as well. Memoization events of ENUM appear 130 times while instantiating int_<fib<2>::value>.

I CC-ed in two guys (Zoltán Porkoláb and Zoltán Borók-Nagy). They will be able to help with Templight related questions.

Regards,
András

Hi,

I'm one of the developers of Metashell (
https://github.com/sabel83/metashell), more specifically the developer of
metadebugger, which was used to reproduce this issue.

Metashell uses Templight (Templight) to gather
information about the template instantiations.

I put together a small test which reproduces the issue without Metashell,
using only a clang patched with Templight:
https://gist.github.com/r0mai/4d90fdc8007af96c2dd1

I don't see any Clang bug here. Templight is not reporting template
instantiations; you're misinterpreting its output. 129 of the 130 instances
are of kind "Memoization", which is Templight's way of saying "Clang
checked whether the type was complete". There are no additional
instantiations here.

Hi,

I'm one of the developers of Metashell (
https://github.com/sabel83/metashell), more specifically the developer
of metadebugger, which was used to reproduce this issue.

Metashell uses Templight (Templight) to gather
information about the template instantiations.

I put together a small test which reproduces the issue without Metashell,
using only a clang patched with Templight:
https://gist.github.com/r0mai/4d90fdc8007af96c2dd1

I don't see any Clang bug here. Templight is not reporting template
instantiations; you're misinterpreting its output. 129 of the 130 instances
are of kind "Memoization", which is Templight's way of saying "Clang
checked whether the type was complete". There are no additional
instantiations here.

Sorry, I missed one; there are two TemplateInstantiations in that log, not
one. One for fib<2> and one for int_<1>.

You can find the trace that Templight produced in the gist as well.

Hi,

I'm one of the developers of Metashell (
https://github.com/sabel83/metashell), more specifically the developer
of metadebugger, which was used to reproduce this issue.

Metashell uses Templight (Templight) to gather
information about the template instantiations.

I put together a small test which reproduces the issue without
Metashell, using only a clang patched with Templight:
https://gist.github.com/r0mai/4d90fdc8007af96c2dd1

I don't see any Clang bug here. Templight is not reporting template
instantiations; you're misinterpreting its output. 129 of the 130 instances
are of kind "Memoization", which is Templight's way of saying "Clang
checked whether the type was complete". There are no additional
instantiations here.

Sorry, I missed one; there are two TemplateInstantiations in that log, not
one. One for fib<2> and one for int_<1>.

Thanks for the explanation. Could you briefly explain what Clang
understands under term «type completeness» regarding enum and why the
compiler does such amount of checks?

Hi,

I'm one of the developers of Metashell (
https://github.com/sabel83/metashell), more specifically the developer
of metadebugger, which was used to reproduce this issue.

Metashell uses Templight (Templight) to gather
information about the template instantiations.

I put together a small test which reproduces the issue without
Metashell, using only a clang patched with Templight:
https://gist.github.com/r0mai/4d90fdc8007af96c2dd1

I don't see any Clang bug here. Templight is not reporting template
instantiations; you're misinterpreting its output. 129 of the 130 instances
are of kind "Memoization", which is Templight's way of saying "Clang
checked whether the type was complete". There are no additional
instantiations here.

Sorry, I missed one; there are two TemplateInstantiations in that log,
not one. One for fib<2> and one for int_<1>.

Thanks for the explanation. Could you briefly explain what Clang
understands under term «type completeness» regarding enum and why the
compiler does such amount of checks?

Any time the compiler examines a case where the completeness of a type
might affect program semantics, it will check whether the type is complete
(and trigger the Templight message you're seeing). Any of these cases
/could/ trigger an instantiation, if they happen to be the first such
check. If you want to understand why all of these are happening, you could
set a breakpoint on the code added by Templight and have a look at the
backtraces (and if you want a spoiler, see PR21280).

You can find the trace that Templight produced in the gist as well.