Bug 81860 - [7 Regression] Call to undefined inline function involving inheriting constructors
Summary: [7 Regression] Call to undefined inline function involving inheriting constru...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.2.0
: P2 normal
Target Milestone: 7.4
Assignee: Marek Polacek
URL:
Keywords: link-failure
: 82297 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-08-16 12:59 UTC by Gustaw Smolarczyk
Modified: 2018-02-19 15:49 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 6.4.0
Known to fail: 7.2.0, 8.0
Last reconfirmed: 2017-08-31 00:00:00


Attachments
Minimized test case that reproduces the issue (143 bytes, text/plain)
2017-08-16 12:59 UTC, Gustaw Smolarczyk
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Gustaw Smolarczyk 2017-08-16 12:59:48 UTC
Created attachment 41987 [details]
Minimized test case that reproduces the issue

It seems that gcc forgets to emit or inline an empty inline constructor when the following are used:
1. An empty template class A with empty constructor A() {} that is the one that is missed
2. A class B with a template constructor (doesn't matter what is templated) that accepts an object of class A with a default argument A() and stores it inside of itself
3. A class C that derives from class B and uses inheriting constructors

Attached is a test-case for this.

$ g++ test-case3.cpp
/tmp/ccoFntWy.o: In function `main':
test-case3.cpp:(.text+0x11): undefined reference to `A<unsigned int>::A()'
collect2: error: ld returned 1 exit status

The problem does occur on gcc 7 and the newest snapshot (tested on godbolt). It does not occur on gcc 6 and gcc 5. As such, it's a regression that first occurs in gcc 7.
Comment 1 Jonathan Wakely 2017-08-31 12:54:20 UTC
Confirmed. The missing symbol is generated if -fno-new-inheriting-ctors is used.
Comment 2 Jonathan Wakely 2017-08-31 13:01:15 UTC
tmp$ g++ test-case3.cpp -c && nm test-case3.o
                 U _ZN1AIjEC1Ev
0000000000000000 W _ZN1BC1IiEET_RK1AIjE
0000000000000000 W _ZN1BC2IiEET_RK1AIjE
0000000000000000 n _ZN1BC5IiEET_RK1AIjE
0000000000000000 W _ZN1CCI11BIiEET_RK1AIjE
0000000000000000 W _ZN1CCI21BIiEET_RK1AIjE
0000000000000000 n _ZN1CCI51BIiEET_RK1AIjE
0000000000000000 T main
tmp$ g++ test-case3.cpp -c -fno-new-inheriting-ctors && nm test-case3.o
0000000000000000 W _ZN1AIjEC1Ev
0000000000000000 W _ZN1AIjEC2Ev
0000000000000000 n _ZN1AIjEC5Ev
0000000000000000 W _ZN1BC1IiEET_RK1AIjE
0000000000000000 W _ZN1BC2IiEET_RK1AIjE
0000000000000000 n _ZN1BC5IiEET_RK1AIjE
0000000000000000 W _ZN1CC1IiEET_
0000000000000000 W _ZN1CC2IiEET_
0000000000000000 n _ZN1CC5IiEET_
0000000000000000 T main
Comment 3 Jonathan Wakely 2017-09-22 13:14:56 UTC
*** Bug 82297 has been marked as a duplicate of this bug. ***
Comment 4 Jonathan Wakely 2017-09-22 13:19:23 UTC
Testcase from PR 82297, which produces an undefined reference for a function used in a default argument of an inherited constructor:

template<class T>
struct bug_t {};

template<class T>
bug_t<T> make_bug(const T&) { return {}; }

template<class T>
struct Test {
  template<class U>
  Test(const U& , const bug_t<U> = make_bug(0)) {}

  /**
   * Also generates an error, at compile time, related bug ?
   */
  // template<class U>
  // Test(const U& , const bug_t<U> = make_bug<U>(0)) {}
};

template<class T>
struct img_t : Test<T> {
  using Test<T>::Test;
};

template<class T = char>
img_t<T> make_img(int val) {
  return {val};
}

int main() {
  make_img(2);
}

/tmp/ccix9VDk.o: In function `img_t<char> make_img<char>(int)':
inh.cc:(.text._Z8make_imgIcE5img_tIT_Ei[_Z8make_imgIcE5img_tIT_Ei]+0x1e): undefined reference to `bug_t<int> make_bug<int>(int const&)'
collect2: error: ld returned 1 exit status
Comment 5 Marek Polacek 2018-01-02 14:28:52 UTC
Fixed by r251426.  I'll add the test at least.  I think it's worth it because I see no lambdas in the testcase.
Comment 6 Marek Polacek 2018-01-02 15:05:40 UTC
Author: mpolacek
Date: Tue Jan  2 15:05:09 2018
New Revision: 256076

URL: https://gcc.gnu.org/viewcvs?rev=256076&root=gcc&view=rev
Log:
	PR c++/81860
	* g++.dg/cpp0x/inh-ctor30.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
Comment 7 Marek Polacek 2018-01-02 15:06:22 UTC
Done.
Comment 8 Gustaw Smolarczyk 2018-01-25 15:43:05 UTC
Hello,

Can I expect the fix to be backported to the gcc 7 branch? gcc 7.3.0 has apparently shipped with the bug still present.
Comment 9 Jonathan Wakely 2018-02-19 14:54:08 UTC
Author: redi
Date: Mon Feb 19 14:53:36 2018
New Revision: 257806

URL: https://gcc.gnu.org/viewcvs?rev=257806&root=gcc&view=rev
Log:
Fix lambdas in template default argument of inherited ctor.

gcc/cp:

Backport from mainline
2017-08-29  Jason Merrill  <jason@redhat.com>

	Fix lambdas in template default argument of inherited ctor.
	* method.c (synthesized_method_base_walk): Replace an inherited
	template with its specialization.
	(synthesized_method_walk): Make inheriting_ctor a pointer.
	(maybe_explain_implicit_delete, explain_implicit_non_constexpr)
	(deduce_inheriting_ctor, implicitly_declare_fn): Adjust.

gcc/testsuite:

Backport from mainline
2018-01-02  Marek Polacek  <polacek@redhat.com>

	PR c++/81860
	* g++.dg/cpp0x/inh-ctor30.C: New test.

Added:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C
    branches/gcc-7-branch/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C
Modified:
    branches/gcc-7-branch/gcc/cp/ChangeLog
    branches/gcc-7-branch/gcc/cp/method.c
    branches/gcc-7-branch/gcc/testsuite/ChangeLog
Comment 10 Jonathan Wakely 2018-02-19 15:49:09 UTC
Fixed for 7.4 now.