Bug 51494 - Legal program rejection - capturing "this" when using static method inside lambda
Summary: Legal program rejection - capturing "this" when using static method inside la...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.1
: P3 normal
Target Milestone: 4.8.0
Assignee: Jason Merrill
URL:
Keywords: rejects-valid
: 55828 (view as bug list)
Depends on:
Blocks: 54367 52183
  Show dependency treegraph
 
Reported: 2011-12-10 05:51 UTC by Maxim Ivanov
Modified: 2013-03-08 16:10 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.7.0
Last reconfirmed: 2011-12-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Maxim Ivanov 2011-12-10 05:51:57 UTC
Consider the following source code:

struct A
{
    static void f() {}

    void foo()
    {
        [] () { f(); };
    }
};


GCC 4.6.1 produces the following error message when compiling it:
test.cpp: In lambda function:
test.cpp:7:27: error: ‘this’ was not captured for this lambda function

However, the member function f is static and it's call doesn't use 'this'; therefore the lambda need not to capture 'this'. The code shall compile.
Comment 1 Paolo Carlini 2011-12-22 01:38:46 UTC
On it.
Comment 2 Andy Lutomirski 2012-05-03 21:53:18 UTC
This seems to have gotten worse in gcc 4.7.  This code is now rejected as well:

This code:

struct A
{
  static void func1() {}
};

template<typename T>
struct B : public A
{
  void func2() const
  {
    func3([&]{ func1(); });
  }
  
  template<typename Func>
  void func3(Func f) const
  {
  }
};

template class B<int>;

The error is:

template_bug.cc: In instantiation of ‘B<T>::func2() const [with T = int]::<lambda()>’:
template_bug.cc:11:22:   required from ‘struct B<T>::func2() const [with T = int]::<lambda()>’
template_bug.cc:11:5:   required from ‘void B<T>::func2() const [with T = int]’
template_bug.cc:20:16:   required from here
template_bug.cc:11:16: error: redeclaration of ‘const B<int>* const B<T>::func2() const [with T = int]::<lambda()>::__this’
template_bug.cc:11:22: note: previous declaration ‘const B<int>* const B<T>::func2() const [with T = int]::<lambda()>::__this’
template_bug.cc:11:16: error: redeclaration of ‘const B<int>* const this’
template_bug.cc:11:22: error: ‘const B<int>* const this’ previously declared here
template_bug.cc:15:8: error: ‘void B<T>::func3(Func) const [with Func = B<T>::func2() const [with T = int]::<lambda()>; T = int]’, declared using local type ‘B<T>::func2() const [with T = int]::<lambda()>’, is used but never defined [-fpermissive]

Your patch fixes this test case, too.
Comment 3 Paolo Carlini 2012-05-03 23:04:35 UTC
A slightly improved patch is available here:

  http://gcc.gnu.org/ml/gcc-patches/2012-02/msg00429.html

but see the comments. I'm not sure I will be able soon enough to address the non-trivial comments and post a new version.
Comment 4 gcc-bugx 2012-06-04 08:21:54 UTC
Probably related error: this capture ignored on explicit instantiation.

--------------------8<---------------
struct A
{
    static void f() {}

    template <typename T>
    void foo()
    {
        [this] () { f(); };
    }
};

template void A::foo<int>();
-------------------->8---------------


Compiler version & output:

$ g++ -std=c++11 -c -v y.cc
Using built-in specs.
COLLECT_GCC=g++
Target: x86_64-unknown-linux-gnu
Configured with: ./configure --enable-languages=c,c++ --prefix=/home/x
Thread model: posix
gcc version 4.7.0 (GCC) 
COLLECT_GCC_OPTIONS='-std=c++11' '-c' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /home/x/libexec/gcc/x86_64-unknown-linux-gnu/4.7.0/cc1plus -quiet -v -D_GNU_SOURCE y.cc -quiet -dumpbase y.cc -mtune=generic -march=x86-64 -auxbase y -std=c++11 -version -o /tmp/ccdFvfri.s
GNU C++ (GCC) version 4.7.0 (x86_64-unknown-linux-gnu)
        compiled by GNU C version 4.7.0, GMP version 4.3.2, MPFR version 3.0.0-p8, MPC version 0.9
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../x86_64-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0
 /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/x86_64-unknown-linux-gnu
 /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/../../../../include/c++/4.7.0/backward
 /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/include
 /usr/local/include
 /home/x/include
 /home/x/lib/gcc/x86_64-unknown-linux-gnu/4.7.0/include-fixed
 /usr/include
End of search list.
GNU C++ (GCC) version 4.7.0 (x86_64-unknown-linux-gnu)
        compiled by GNU C version 4.7.0, GMP version 4.3.2, MPFR version 3.0.0-p8, MPC version 0.9
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: ...
y.cc: In instantiation of ‘A::foo() [with T = int]::<lambda()>’:
y.cc:8:4:   required from ‘struct A::foo() [with T = int]::<lambda()>’
y.cc:8:3:   required from ‘void A::foo() [with T = int]’
y.cc:11:27:   required from here
y.cc:8:17: error: ‘this’ was not captured for this lambda function
Comment 5 Jason Merrill 2012-06-04 19:35:40 UTC
The testcases in comments 2 and 4 are PR 53137, which is fixed for 4.7.1.
Comment 6 Paolo Carlini 2012-08-16 09:53:36 UTC
Not actively working on this.
Comment 7 kpx1894 2012-12-07 15:18:03 UTC
This bug is still present in GCC 4.7.2. There are cases where capturing "this" (as a workaround) is not possible:
----------
#include <iostream>

struct Test
{
    void (*get())()
    {
        return [](){ Test::sf(); };
    }

    static void sf()
    {
        std::cout << "Test::sf" << std::endl;
    }

};

int main()
{
    Test test;

    auto f = test.get();
    (*f)();
}
----------
Comment 8 Jason Merrill 2013-03-04 18:15:08 UTC
*** Bug 55828 has been marked as a duplicate of this bug. ***
Comment 9 Jason Merrill 2013-03-08 16:03:57 UTC
Author: jason
Date: Fri Mar  8 16:03:48 2013
New Revision: 196549

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=196549
Log:
	PR c++/51494
	PR c++/51884
	PR c++/56222
	* tree.c (maybe_dummy_object): Don't capture 'this'.
	* semantics.c (maybe_resolve_dummy): New.
	(finish_non_static_data_member): Use it.
	(finish_qualified_id_expr): Don't test is_dummy_object.
	* cp-tree.h: Declare maybe_resolve_dummy.
	* call.c (build_new_method_call_1): Use it.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this11.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/semantics.c
    trunk/gcc/cp/tree.c
Comment 10 Jason Merrill 2013-03-08 16:10:48 UTC
Fixed for 4.8.