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, wrong-code
Depends on:
Blocks: lambdas
  Show dependency treegraph
 
Reported: 2013-05-27 21:29 UTC by Oleksii Shevchuk
Modified: 2024-07-18 08:06 UTC (History)
3 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.
Comment 3 GCC Commits 2024-07-18 08:06:51 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:e217e7dbdc1040e7ee160796e9ca1ef12a0dd1cb

commit r15-2136-ge217e7dbdc1040e7ee160796e9ca1ef12a0dd1cb
Author: Sam James <sam@gentoo.org>
Date:   Thu Jul 18 10:00:17 2024 +0200

    testsuite: Add dg-do run to more tests
    
    All of these are for wrong-code bugs.  Confirmed to be used before but
    with no execution.
    
    2024-07-18  Sam James  <sam@gentoo.org>
    
            PR c++/53288
            PR c++/57437
            PR c/65345
            PR libstdc++/88101
            PR tree-optimization/96369
            PR tree-optimization/102124
            PR tree-optimization/108692
            * c-c++-common/pr96369.c: Add dg-do run directive.
            * gcc.dg/torture/pr102124.c: Ditto.
            * gcc.dg/pr108692.c: Ditto.
            * gcc.dg/atomic/pr65345-4.c: Ditto.
            * g++.dg/cpp0x/lambda/lambda-return1.C: Ditto.
            * g++.dg/init/lifetime4.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-1.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-2.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-3.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-4.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-5.C: Ditto.