Bug 57437 - [4.7/4.8/4.9 Regression] C++11: mutable lambdas
Summary: [4.7/4.8/4.9 Regression] C++11: mutable lambdas
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.3
: P3 normal
Target Milestone: 4.7.4
Assignee: Jason Merrill
URL:
Keywords: c++-lambda
Depends on:
Blocks: lambdas
  Show dependency treegraph
 
Reported: 2013-05-27 21:29 UTC by Oleksii Shevchuk
Modified: 2022-03-11 00:32 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.6.3
Known to fail:
Last reconfirmed: 2013-05-28 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Oleksii Shevchuk 2013-05-27 21:29:07 UTC
> cat test.cpp
#include <vector>
#include <iostream>

int main(int argc, char *argv[])
{
  auto x = std::vector<int>({1, 2, 3});

  auto y = [x] () 
    mutable {
    for (auto &i: x)
      i ++;
    return x;
  };
  
  for (const auto &i: y())
    std::cout << i << std::endl;

  for (const auto &i: y())
    std::cout << i << std::endl;
  
  return 0;
}

> x86_64-pc-linux-gnu-g++-4.6.3 -o test test.cpp -std=gnu++0x
> ./test
2
3
4
3
4
5
> LC_ALL=C x86_64-pc-linux-gnu-g++-4.6.3 -v 
Using built-in specs.
COLLECT_GCC=x86_64-pc-linux-gnu-g++-4.6.3
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.6.3/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/portage/sys-devel/gcc-4.6.3/work/gcc-4.6.3/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.6.3 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.6.3 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.6.3/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.6.3/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.6.3/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --with-ppl --with-cloog --disable-ppl-version-check --with-cloog-include=/usr/include/cloog-ppl --enable-lto --enable-nls --without-included-gettext --with-system-zlib --enable-obsolete --disable-werror --enable-secureplt --enable-multilib --enable-libmudflap --disable-libssp --enable-esp --enable-libgomp --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.6.3/python --enable-checking=release --disable-libgcj --enable-libstdcxx-time --enable-languages=c,c++,objc,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-targets=all --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo Hardened 4.6.3 p1.11, pie-0.5.2'
Thread model: posix
gcc version 4.6.3 (Gentoo Hardened 4.6.3 p1.11, pie-0.5.2)


> x86_64-pc-linux-gnu-g++-4.7.2 -o test2 test.cpp -std=gnu++0x 
> ./test2
2
3
4

> LC_ALL=C x86_64-pc-linux-gnu-g++-4.7.2 -v     
Using built-in specs.
COLLECT_GCC=x86_64-pc-linux-gnu-g++-4.7.2
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.7.2/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/portage/sys-devel/gcc-4.7.2-r1/work/gcc-4.7.2/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.7.2 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.2/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.7.2 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.7.2/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.7.2/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.2/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --with-ppl --with-cloog --disable-ppl-version-check --with-cloog-include=/usr/include/cloog-ppl --enable-lto --enable-nls --without-included-gettext --with-system-zlib --enable-obsolete --disable-werror --enable-secureplt --enable-multilib --with-multilib-list=m32,m64 --enable-libmudflap --disable-libssp --enable-esp --enable-libgomp --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.7.2/python --enable-checking=release --disable-libgcj --enable-libstdcxx-time --enable-languages=c,c++,objc,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-targets=all --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo Hardened 4.7.2-r1 p1.5, pie-0.5.5'
Thread model: posix
gcc version 4.7.2 (Gentoo Hardened 4.7.2-r1 p1.5, pie-0.5.5)

> x86_64-pc-linux-gnu-g++-4.8.0 -o test test.cpp -std=gnu++11
> ./test
2
3
4

> LC_ALL=C x86_64-pc-linux-gnu-g++-4.8.0 -v
Using built-in specs.
COLLECT_GCC=x86_64-pc-linux-gnu-g++-4.8.0
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.8.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /tmp/portage/sys-devel/gcc-4.8.0/work/gcc-4.8.0/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.8.0 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.0/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.0 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.0/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.8.0/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.0/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --with-ppl --with-cloog --disable-isl-version-check --with-cloog --enable-lto --enable-nls --without-included-gettext --with-system-zlib --enable-obsolete --disable-werror --enable-secureplt --enable-multilib --with-multilib-list=m32,m64 --disable-libmudflap --disable-libssp --enable-esp --enable-libgomp --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/4.8.0/python --enable-checking=release --disable-libgcj --enable-libstdcxx-time --disable-libquadmath --enable-languages=c,c++ --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-targets=all --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo Hardened 4.8.0 p1.2, pie-0.5.5'
Thread model: posix
gcc version 4.8.0 (Gentoo Hardened 4.8.0 p1.2, pie-0.5.5)
Comment 1 Daniel Krügler 2013-05-28 06:40:52 UTC
I can confirm the problem for my mingw-64-bit system using gcc 4.9.0 20130519 (experimental).

A variation of the program:

//-------------------------------------------------
#include <vector>
#include <iostream>

int main()
{
  std::vector<int> x{1, 2, 3};

  auto y = [x] () mutable {
    for (auto &i: x)
      i++;
    return x;
  };

  for (const auto &i : y()) {
    std::cout << i << std::endl;
  }

  std::cout << "(1)" << std::endl;

  for (const auto &i : y()) {
    std::cout << i << std::endl;
  }

  std::cout << "(2)" << std::endl;
}
//-------------------------------------------------

produces the output:

2
3
4
(1)
(2)

I *think* the following is going on here: The actual closure member x is (incorrectly) considered as a local variable during RVO analysis, therefore the first invocation invokes the move constructor on that member with the effect of leaving an empty vector x within the closure.

The behavior looks incorrect to me: Neither 12.8 p31 b1 nor p32 can be applied here, because x is neither a variable with automatic storage duration nor a function parameter. It is correct the 5.1.2 p10 says 

"The identifier in a simple-capture is looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find a variable with automatic storage duration declared in the reaching scope of the local lambda expression."

but this is an automatic variable *not* within the closure's function call operator. And 5.1.2 p15

"For each entity captured by copy, an unnamed nonstatic data member is declared in the closure type."

is clear that x is considered a data member within the closure and RVO shall not be applied to it.
Comment 2 Jason Merrill 2013-07-09 18:52:53 UTC
Fixed for 4.7.4/4.8.2/4.9.