GCC Bugzilla has been upgraded from version 4.4.9 to 5.0rc3. If you see any problem, please report it to bug 64968.
Bug 55015 - [4.7/4.8 Regression] Lambda functions not found at link time when declared in an inline function
Summary: [4.7/4.8 Regression] Lambda functions not found at link time when declared in...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.2
: P2 normal
Target Milestone: 4.7.3
Assignee: Jason Merrill
URL:
Keywords: assemble-failure
: 54801 55178 55472 55607 (view as bug list)
Depends on:
Blocks: 54367
  Show dependency treegraph
 
Reported: 2012-10-22 02:09 UTC by Julien Nitard
Modified: 2012-12-06 15:44 UTC (History)
11 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.7.1
Known to fail: 4.7.2, 4.8.0
Last reconfirmed: 2012-10-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Julien Nitard 2012-10-22 02:09:54 UTC
Hi all,

Following this stackoverflow question http://stackoverflow.com/questions/13003941/lambda-not-found-when-defined-in-an-inline-function-in-g-4-7, I was directed here to report a bug.
I have tried to find similar bugs but haven't.

Lambdas are not handled properly when declared inside inline functions (or so it seems).

Here is a LWS link that demonstrates the error:
http://liveworkspace.org/code/35374b3c9b0d40e8ccc0819eb44d7f9e


In case the link disappears, here the source:

#include <stdexcept>
#include <string>

#include <boost/algorithm/string.hpp>

using std::string;

typedef bool (*FieldComparer)(const std::string&, const std::string&);

inline FieldComparer
GetComparer(const std::string& query, string& separator)
{
    if (query.find('=') != std::string::npos) {
        separator = "=";
        return [](const string& s1, const string& s2) { return s1 == s2; };
    }
    else if (query.find('^') != string::npos) {
        separator = "^";
        return [](const string& s1, const string& s2) { return boost::starts_with(s1, s2); };
    }
    else if (query.find('*') != string::npos) {
        separator = "*";
        return [](const string& s1, const string& s2) { return boost::contains(s1, s2); };
    }
    else if (query.find('!') != string::npos) {
        separator = "!";
        return [](const string& s1, const string& s2) { return s1 != s2; };
    }
    else
        throw std::invalid_argument("Search: could not find operator in query string.");
}

int main()
{
  std::string sep;
  auto comp = GetComparer( "=", sep );
}

Many thanks,
Comment 1 Julien Nitard 2012-10-22 02:13:43 UTC
Somebody noted in S.O. that declaring the inline function "static" (or using an anonymous namespace which I guess as same effect) hides (or solves ;) the problem.
Comment 2 Robert Xiao 2012-10-22 05:02:01 UTC
Minimal reproducible testcase:

    typedef void (*VoidFunc)();
    inline VoidFunc GetFunc() { return [](){}; }
    int main() { VoidFunc func = GetFunc(); }

Compiled with gcc version 4.7.2 (MacPorts gcc47 4.7.2_2). Output:

$ g++-mp-4.7 test.cpp -std=c++11
Undefined symbols for architecture x86_64:
  "GetFunc()::{lambda()#1}::_FUN()", referenced from:
      GetFunc()::{lambda()#1}::operator void (*)()() const in cciEeUag.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
Comment 3 Andrew Pinski 2012-10-22 05:09:36 UTC
Confirmed on the trunk too.
Comment 4 Paolo Carlini 2012-11-02 11:10:49 UTC
*** Bug 55178 has been marked as a duplicate of this bug. ***
Comment 5 Paolo Carlini 2012-11-26 23:37:48 UTC
This is a regression.
Comment 6 Paolo Carlini 2012-11-27 10:26:03 UTC
HJ, can you help finding which change broke this? In Comment #2 there is a very short testcase (it's pretty old, I guess you want -std=c++0x, not -std=c++11 in the command line)
Comment 8 Paolo Carlini 2012-11-27 11:02:42 UTC
Never mind, it's very easy, it's the following change, the fix for PR53821:

   http://gcc.gnu.org/viewcvs?view=revision&revision=189176

And PR55472 is a duplicate, reverting the above fixes it too.
Comment 9 Paolo Carlini 2012-11-27 11:03:54 UTC
*** Bug 55472 has been marked as a duplicate of this bug. ***
Comment 10 Paolo Carlini 2012-12-06 11:32:25 UTC
*** Bug 55607 has been marked as a duplicate of this bug. ***
Comment 11 Jason Merrill 2012-12-06 14:37:23 UTC
Author: jason
Date: Thu Dec  6 14:37:13 2012
New Revision: 194251

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=194251
Log:
	PR c++/55015
	PR c++/53821
	* semantics.c (maybe_add_lambda_conv_op): Revert earlier change.
	* decl.c (start_preparsed_function): Make local class methods comdat
	in templates, too.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv6.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/decl.c
    trunk/gcc/cp/semantics.c
Comment 12 Jason Merrill 2012-12-06 14:39:57 UTC
Author: jason
Date: Thu Dec  6 14:39:52 2012
New Revision: 194253

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=194253
Log:
	PR c++/55015
	PR c++/53821
	* semantics.c (maybe_add_lambda_conv_op): Revert earlier change.
	* decl.c (start_preparsed_function): Make local class methods comdat
	in templates, too.

Added:
    branches/gcc-4_7-branch/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv6.C
Modified:
    branches/gcc-4_7-branch/gcc/cp/ChangeLog
    branches/gcc-4_7-branch/gcc/cp/decl.c
    branches/gcc-4_7-branch/gcc/cp/semantics.c
Comment 13 Jason Merrill 2012-12-06 14:42:45 UTC
Fixed for 4.7.3.
Comment 14 Paolo Carlini 2012-12-06 15:44:50 UTC
*** Bug 54801 has been marked as a duplicate of this bug. ***