Bug 53821 - [4.7/4.8 regression][c++11] multiple definitions of lambda
Summary: [4.7/4.8 regression][c++11] multiple definitions of lambda
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.8.0
: P1 normal
Target Milestone: 4.7.2
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 53675 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-06-30 15:22 UTC by vincenzo Innocente
Modified: 2012-12-06 14:39 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.7.1
Known to fail:
Last reconfirmed: 2012-06-30 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description vincenzo Innocente 2012-06-30 15:22:59 UTC
this is a regression as not happening in 4.6.2 and 4.7.1
I personally think that the template methods SHOULD be declared inline if included in multiple sources…

anyhow since it was discussed at length  in PR53780 and PR53768
and got attention from developers I promised to reduce and post

cat inlT.cc
#include <algorithm>
template<typename T> struct Foo {
   
   virtual int bar(int,int);
   int k;
};

// int ebar(int,int) __attribute__ ((visibility ("default")));


template<typename T> 
int Foo<T>::bar(int i, int j) {
  auto ebar = [](int a, int b) { return a+b;};
  static int a=i;
  if (i>0) k = ebar(i,j);
  if (j>0) k = ebar(j,i);
  if (i>0) k = ebar(j,i);
  if (k>0) k = ebar(i,j);
  return (a==i) ? i : j;
}


struct A1 {

  Foo<float> * foo;

};


int __attribute__ ((visibility ("default")))  hello1 (int i, int j) { A1 a; return a.foo->bar(i,j);} 

[vocms123] ~/public/ctest/bugs48 $ cat inlT2.cc
#include <algorithm>
template<typename T> struct Foo {
   
   virtual int bar(int,int);
   int k;
};

// int ebar(int,int) __attribute__ ((visibility ("default")));


template<typename T> 
int Foo<T>::bar(int i, int j) {
  auto ebar = [](int a, int b) { return a+b;};
  static int a=i;
  if (i>0) k = ebar(i,j);
  if (j>0) k = ebar(j,i);
  if (i>0) k = ebar(j,i);
  if (k>0) k = ebar(i,j);
  return (a==i) ? i : j;
}


struct A2 {

  Foo<float> * foo;

};

int __attribute__ ((visibility ("default")))  hello2 (int i, int j) { A2 a; return a.foo->bar(i,j);} 


[vocms123] ~/public/ctest/bugs48 $ cat buildInlT
c++ -std=gnu++11 -O2 -fvisibility-inlines-hidden -fvisibility=hidden -flto -c inlT.cc  -fPIC
c++ -std=gnu++11 -O2 -fvisibility-inlines-hidden -fvisibility=hidden -flto -c inlT2.cc -fPIC
c++ -std=gnu++11 -O2 -fvisibility-inlines-hidden -fvisibility=hidden -flto -shared inlT.o inlT2.o -fPIC -o inlT.so

source buildInlT
/afs/cern.ch/user/i/innocent/w3/gcc47slc5/bin/ld: error: inlT2.o: multiple definition of 'Foo<float>::bar(int, int)::{lambda(int, int)#1}::_FUN(int, int)'
/afs/cern.ch/user/i/innocent/w3/gcc47slc5/bin/ld: inlT.o: previous definition here
/afs/cern.ch/user/i/innocent/w3/gcc47slc5/bin/ld: error: inlT2.o: multiple definition of 'Foo<float>::bar(int, int)::{lambda(int, int)#1}::operator int (*)(int, int)() const'
/afs/cern.ch/user/i/innocent/w3/gcc47slc5/bin/ld: inlT.o: previous definition here
collect2: error: ld returned 1 exit status

also with simpler
cat buildInlT0
c++ -std=gnu++11 -O2    -c inlT.cc  -fPIC
c++ -std=gnu++11 -O2    -c inlT2.cc -fPIC
c++ -std=gnu++11 -O2    -shared inlT.o inlT2.o -fPIC -o inlT.so
 source buildInlT0
/afs/cern.ch/user/i/innocent/w3/gcc47slc5/bin/ld: error: inlT2.o: multiple definition of 'Foo<float>::bar(int, int)::{lambda(int, int)#1}::_FUN(int, int)'
/afs/cern.ch/user/i/innocent/w3/gcc47slc5/bin/ld: inlT.o: previous definition here
/afs/cern.ch/user/i/innocent/w3/gcc47slc5/bin/ld: error: inlT2.o: multiple definition of 'Foo<float>::bar(int, int)::{lambda(int, int)#1}::operator int (*)(int, int)() const'
/afs/cern.ch/user/i/innocent/w3/gcc47slc5/bin/ld: inlT.o: previous definition here


c++ -v
Using built-in specs.
COLLECT_GCC=c++
COLLECT_LTO_WRAPPER=/afs/cern.ch/user/i/innocent/w3/gcc47slc5/libexec/gcc/x86_64-unknown-linux-gnu/4.7.2/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-4.7/configure --enable-languages=c,c++,fortran --disable-multilib --enable-gold=yes --disable-nls --enable-lto --with-mpc=/afs/cern.ch/cms/slc5_amd64_gcc470/external/gcc/4.7.0 --with-gmp=/afs/cern.ch/cms/slc5_amd64_gcc470/external/gcc/4.7.0 --with-mpfr=/afs/cern.ch/cms/slc5_amd64_gcc470/external/gcc/4.7.0 --prefix=/afs/cern.ch/user/i/innocent/w3/gcc47slc5 --with-build-time-tools=/build/ge/new-binutils/a/slc5_amd64_gcc470/external/gcc/4.7.0-cms/bin
Thread model: posix
gcc version 4.7.2 20120629 (prerelease) [gcc-4_7-branch revision 189081] (GCC) 
[vocms123] ~/public/ctest/bugs48 $ ld -v
GNU gold (GNU Binutils 2.22.52.20120515) 1.11
Comment 1 vincenzo Innocente 2012-06-30 15:33:15 UTC
to clarify: 
in compiles and links correctly provided that
template<typename T> 
inline
int Foo<T>::bar(int i, int j)

or if instead of the lambda "bar" invokes the external "ebar"
Comment 2 H.J. Lu 2012-06-30 19:22:16 UTC
It is caused by revision 188117:

http://gcc.gnu.org/ml/gcc-cvs/2012-06/msg00027.html
Comment 3 Jonathan Wakely 2012-07-02 10:07:17 UTC
This is PR 53675
Comment 4 Jason Merrill 2012-07-02 19:14:40 UTC
Author: jason
Date: Mon Jul  2 19:14:34 2012
New Revision: 189175

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=189175
Log:
	PR c++/53821
	* semantics.c (maybe_add_lambda_conv_op): Don't set
	DECL_INTERFACE_KNOWN.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template6.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/semantics.c
    trunk/gcc/testsuite/ChangeLog
Comment 5 Jason Merrill 2012-07-02 19:15:03 UTC
Author: jason
Date: Mon Jul  2 19:14:58 2012
New Revision: 189176

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=189176
Log:
	PR c++/53821
	* semantics.c (maybe_add_lambda_conv_op): Don't set
	DECL_INTERFACE_KNOWN.

Added:
    branches/gcc-4_7-branch/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template6.C
Modified:
    branches/gcc-4_7-branch/gcc/cp/ChangeLog
    branches/gcc-4_7-branch/gcc/cp/semantics.c
    branches/gcc-4_7-branch/gcc/testsuite/ChangeLog
Comment 6 Jason Merrill 2012-07-02 19:25:28 UTC
Fixed.
Comment 7 vincenzo Innocente 2012-07-03 20:39:50 UTC
I'm still wandering, more in general, if there is a semantic difference between


template<typename T> 
int Foo<T>::bar(int i, int j) {
…
}

and

template<typename T> 
inline
int Foo<T>::bar(int i, int j) {
…
}
Comment 8 Jonathan Wakely 2012-07-03 20:55:25 UTC
*** Bug 53675 has been marked as a duplicate of this bug. ***
Comment 9 Jason Merrill 2012-07-03 21:28:02 UTC
The only difference is the hint to the compiler that you want the function to be inlined.
Comment 10 Jason Merrill 2012-12-06 14:37:25 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 11 Jason Merrill 2012-12-06 14:39:58 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