I found some strange behaviour that, after a discussion on StackOverflow, seems to be a bug (discussion here: http://stackoverflow.com/questions/16057690/confusion-about-constant-expressions/16068953?noredirect=1#16068953). It seems that GCC implements N3471 which means that every function of an std::initializer_list are constexpr. When trying to pass simple constexpr things in the initializer_list, it works fine: #include <array> #include <initializer_list> int main() { constexpr std::array<int, 3> a = {{ 1, 2, 3 }}; constexpr int a0 = a[0]; constexpr int a1 = a[1]; constexpr int a2 = a[2]; constexpr std::initializer_list<int> b = { a0, a1, a2 }; return 0; } However, without the intermediate variables a0, a1 and a2, the example above crashes: #include <array> #include <initializer_list> int main() { constexpr std::array<int, 3> a = {{ 1, 2, 3 }}; constexpr std::initializer_list<int> b = { a[0], a[1], a[2] }; return 0; } The error is the following one: error: 'const std::initializer_list<int>{((const int*)(&<anonymous>)), 3u}' is not a constant expression This last example works fine if I remove the constexpr qualifier at the beginning of the line or if I replace the initializer_list by a std::array. It seems that the bug is only triggered when using std::initializer_list with constexpr.
I don't see the compiler *crashing*, I see it *rejecting* the snippet.
I get also a similar bug: #include <initializer_list> //is accepted by gcc constexpr std::initializer_list<int> good1 = { 1, 2, 3 }; struct foo { int a, b; }; //still ok constexpr foo good2 = { 1, 2 }; //gcc rejects this constexpr std::initializer_list<foo> bad = { { 1, 2 }, { 3, 4} }; Compiling this gives a similar error: test.cc:12:64: error: ‘const std::initializer_list<foo>{((const foo*)(& _ZGRL3bad0)), 2u}’ is not a constant expression
(In reply to comment #1) > I don't see the compiler *crashing*, I see it *rejecting* the snippet. Indeed, sorry for the poor formulation.
(In reply to Matheus Izvekov from comment #2) > I get also a similar bug: > > #include <initializer_list> > > //is accepted by gcc > constexpr std::initializer_list<int> good1 = { 1, 2, 3 }; > > struct foo { int a, b; }; > > //still ok > constexpr foo good2 = { 1, 2 }; > > //gcc rejects this > constexpr std::initializer_list<foo> bad = { { 1, 2 }, { 3, 4} }; A variation of the last line also produces the same error: constexpr std::initializer_list<foo> bad2 = { good2, good2 }; I can confirm that the error also occurs for the trunk, tested with gcc 4.9.0 20130519 (experimental).
This is fixed in 4.9.1 and mainline. I'm adding a reduced testcase and closing the bug.
Author: paolo Date: Fri Aug 29 13:12:02 2014 New Revision: 214729 URL: https://gcc.gnu.org/viewcvs?rev=214729&root=gcc&view=rev Log: 2014-08-29 Paolo Carlini <paolo.carlini@oracle.com> PR c++/56991 * g++.dg/cpp0x/constexpr-56991.C: New. Added: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-56991.C Modified: trunk/gcc/testsuite/ChangeLog