GCC bug. [dcl.spec.auto]/p7 (quoting N4527):
When a variable declared using a placeholder type is initialized,
[...] the deduced return type or variable type is determined from the
type of its initializer. [...] Otherwise, let T
be the declared type
of the variable [...]. If the placeholder is the auto
type-specifier, the deduced type is determined using the rules for template argument deduction. If the initialization is
direct-list-initialization [...]. [...] Otherwise, obtain P
from T
by replacing the occurrences of auto
with either a new invented
type template parameter U
or, if the initialization is
copy-list-initialization, with std::initializer_list<U>
. Deduce a value for U
using the rules of template argument deduction from a
function call (14.8.2.1), where P
is a function template parameter
type and the corresponding argument is the initializer [...]. If the
deduction fails, the declaration is ill-formed. Otherwise, the type
deduced for the variable or return type is obtained by substituting
the deduced U
into P
.
Thus, in const auto l2 = { 1, 2, 3 };
, deduction is performed as if for the function template
template<class U> void meow(const std::initializer_list<U>);
given the call meow({1, 2, 3})
.
Now consider the const-less case auto l3 = { 1, 2, 3 };
(which GCC correctly deduces as std::initializer_list<int>
). Deduction in this case is performed as if for the function template
template<class U> void purr(std::initializer_list<U>);
given the call purr({1, 2, 3})
.
Since top-level cv-qualification of function parameters are ignored, it should be obvious that the two deduction should yield the same type.
[temp.deduct.call]/p1:
Template argument deduction is done by comparing each function
template parameter type (call it P
) with the type of the
corresponding argument of the call (call it A
) as described below.
If P
is a dependent type, removing references and cv-qualifiers from
P
gives std::initializer_list<P'>
[...] for some P'
[...] and
the argument is a non-empty initializer list (8.5.4), then deduction
is performed instead for each element of the initializer list, taking
P'
as a function template parameter type and the initializer element
as its argument.
Deducing P'
(which is U
) against 1
, 2
, or 3
, all literals of type int
, obviously yields int
.