Bug 56991 - constexpr std::initializer_list rejects too complex initialization
Summary: constexpr std::initializer_list rejects too complex initialization
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: 4.9.1
Assignee: Not yet assigned to anyone
URL: http://stackoverflow.com/q/16057690/1...
Keywords:
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2013-04-17 20:10 UTC by Morwenn
Modified: 2014-08-29 13:12 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.6.4, 4.7.2, 4.7.3, 4.8.0, 4.8.1
Last reconfirmed: 2013-05-24 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Morwenn 2013-04-17 20:10:17 UTC
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.
Comment 1 Paolo Carlini 2013-04-18 07:50:36 UTC
I don't see the compiler *crashing*, I see it *rejecting* the snippet.
Comment 2 Matheus Izvekov 2013-04-18 08:10:19 UTC
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
Comment 3 Morwenn 2013-04-18 08:12:44 UTC
(In reply to comment #1)
> I don't see the compiler *crashing*, I see it *rejecting* the snippet.

Indeed, sorry for the poor formulation.
Comment 4 Daniel Krügler 2013-05-24 10:50:31 UTC
(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).
Comment 5 Paolo Carlini 2014-08-29 13:09:51 UTC
This is fixed in 4.9.1 and mainline. I'm adding a reduced testcase and closing the bug.
Comment 6 paolo@gcc.gnu.org 2014-08-29 13:12:34 UTC
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