Bug 54947 - [4.7/4.8 Regression] [C++11] lambda cannot capture-by-copy inside braced-init-list
Summary: [4.7/4.8 Regression] [C++11] lambda cannot capture-by-copy inside braced-init...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P2 normal
Target Milestone: 4.7.3
Assignee: Jason Merrill
URL:
Keywords: c++-lambda, rejects-valid
Depends on:
Blocks: lambdas
  Show dependency treegraph
 
Reported: 2012-10-17 13:11 UTC by Jonathan Wakely
Modified: 2022-03-11 00:32 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-11-07 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2012-10-17 13:11:19 UTC
struct X
{
  template<typename L>
    X(L)
    { }
};

template<typename A>
  void
  test()
  {
    int i = 0;

    A a_ok_1( [=] { return i; } );  // OK
    A a_ok_2( [i] { return i; } );  // OK

    A a_err_1{ [i] { return i; } };  // error
    A a_err_2{ [=] { return i; } };  // error
  }

int main()
{
  test<X>();
}


lam.cc:17:17: error: the value of ‘i’ is not usable in a constant expression
     A a_err_1{ [i] { return i; } };  // error
                 ^
lam.cc:12:9: note: ‘int i’ is not const
     int i = 0;
         ^
lam.cc:18:17: error: expression ‘<erroneous-expression> = <erroneous-expression>’ is not a constant-expression
     A a_err_2{ [=] { return i; } };  // error
                 ^

There's no error when using direct-initialization, only list-initialization.
No error if test() is not a function template.

Works fine with 4.6 and clang++
Comment 1 Jakub Jelinek 2012-11-07 10:01:02 UTC
Started with http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=176530
This clashes with the C99 designated initializers (as GNU extension for C++).
Guess perhaps the designated array initializers need to be parsed tentatively for C++11, and if they aren't valid, we'd retry as lambdas.
It seems that C++ only supports the C99 style array designators ([constant] = something) which aren't ambiguous with lambdas (unlike the old [constant] something), are they?

Note that
constexpr int i = 0;
int a[] = { [i] = 0 };
ICEs currently with -std=gnu++11.
Comment 2 Jonathan Wakely 2012-11-07 12:15:04 UTC
(In reply to comment #1)
> Guess perhaps the designated array initializers need to be parsed tentatively
> for C++11, and if they aren't valid, we'd retry as lambdas.

Shouldn't we try as lambdas, and if not valid retry as non-standard designated initializers?  If it's ambiguous we should assume it's a standard C+ not the extension.
Comment 3 Jakub Jelinek 2012-11-07 12:24:46 UTC
I think it is unambiguous, as for designated initializer there needs to be = after ], while for lambda {, right?
The thing with tentative parsing is that no diagnostics is emitted during it (or shouldn't), so you might sometimes do tentative parsing of both possibilities and
if neither works, choose one somehow and parse definitely that way to get diagnostics.
Comment 4 Jonathan Wakely 2012-11-07 12:29:28 UTC
(In reply to comment #3)
> I think it is unambiguous, as for designated initializer there needs to be =
> after ],

Ah yes, that's true.

> while for lambda {, right?

Or ( for a parameter list, e.g. [](int i) { return i; }

But you're right, it shouldn't be ambiguous.
Comment 5 Jason Merrill 2012-12-06 14:40:12 UTC
Author: jason
Date: Thu Dec  6 14:40:04 2012
New Revision: 194254

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=194254
Log:
	PR c++/54947
	* parser.c (cp_parser_initializer_list): Don't require an
	expression in [] to be constant until we know it's a C99
	designator.

Added:
    branches/gcc-4_7-branch/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-initlist2.C
Modified:
    branches/gcc-4_7-branch/gcc/cp/ChangeLog
    branches/gcc-4_7-branch/gcc/cp/parser.c
Comment 6 Jason Merrill 2012-12-06 14:45:15 UTC
Author: jason
Date: Thu Dec  6 14:45:11 2012
New Revision: 194256

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=194256
Log:
	PR c++/54947
	* parser.c (cp_parser_initializer_list): Don't require an
	expression in [] to be constant until we know it's a C99
	designator.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-initlist2.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/parser.c
Comment 7 Jason Merrill 2012-12-06 14:46:18 UTC
Fixed for 4.7.3.