Bug 82352 - [7 Regression] comdat-local function called by void h::i() outside its comdat
Summary: [7 Regression] comdat-local function called by void h::i() outside its comdat
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: other (show other bugs)
Version: 7.2.1
: P2 normal
Target Milestone: 7.3
Assignee: Martin Liška
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2017-09-28 16:07 UTC by Holger Hopp
Modified: 2018-03-10 18:46 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work: 8.0
Known to fail:
Last reconfirmed: 2017-09-29 00:00:00


Attachments
Reduced single compilation unit test-case (202 bytes, text/plain)
2017-09-29 09:02 UTC, Martin Liška
Details
Untested patch (1.16 KB, patch)
2018-01-03 10:12 UTC, Martin Liška
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Holger Hopp 2017-09-28 16:07:23 UTC
I'm getting linker error
`...' referenced in section `...' of ..: defined in discarded section `...' of ...
with gcc-7 compiled code, that do not appear with gcc-5 or gcc-6.

Source:

typedef long unsigned int size_t;

class A
{
public :
  typedef enum { Zero = 0, One = 1 } tA;
  A(tA a) { m_a = a; }

private :
  tA m_a;
};

class B
{
public :
  void *operator new(size_t t) { return (void*)(42); };
};

class C
{
public:
  virtual void ffff () = 0;
};

class D
{
 public :
  virtual void g() = 0;
  virtual void h() = 0;
};

template<class T> class IIII: public T, public D
{
public:
 void ffff()
 {
   if (!m_i2) throw A(A::One);
 };

 void h()
 {
  if (m_i2) throw A(A::Zero);
 }

protected:
 virtual void g()
 {
  if (m_i1 !=0) throw A(A::Zero);
 };

private :
 int m_i1;
 void *m_i2;
};

class E
{
private:
    size_t m_e;
    static const size_t Max;

public:
    E& i(size_t a, size_t b, size_t c)
    {
        if ((a > Max) || (c > Max)) throw A(A::Zero );
        if (a + b > m_e) throw A(A::One );
        return (*this);
    }

  inline E& j(const E &s)
    {
      return i(0,0,s.m_e);
    }
};

class F : public C { };
class G : public C { };
class HHHH : public B, public F, public G { };

void k()
{
    HHHH *p = new IIII<HHHH>();
}

void l()
{
  E e1, e2;
  e1.j(e2);
}



Reproduce:

$ g++ -O2 -o t1.o -c t1.cpp && echo ok && objdump -t t1.o | grep ffffEv.part
ok
0000000000000000 l    d  .text.unlikely._ZN4IIIII4HHHHE4ffffEv.part.2	0000000000000000 .text.unlikely._ZN4IIIII4HHHHE4ffffEv.part.2
0000000000000000 l     F .text.unlikely._ZN4IIIII4HHHHE4ffffEv.part.2	0000000000000023 _ZN4IIIII4HHHHE4ffffEv.part.2

This symbol is causing the linker problem. Maybe this is already sufficient for you.
You may get the final linker error as follows:

Slightly change source t1.cpp to t2.cpp:
- remove function g() (twice!)
- rename k() and l() by k2() and l2(2), respectively.

$ g++ -O2 -o t2.o -c t2.cpp && echo ok && objdump -t t2.o | grep ffffEv.part
ok
0000000000000000 l    d  .text.unlikely._ZN4IIIII4HHHHE4ffffEv.part.1	0000000000000000 .text.unlikely._ZN4IIIII4HHHHE4ffffEv.part.1
0000000000000000 l     F .text.unlikely._ZN4IIIII4HHHHE4ffffEv.part.1	0000000000000023 _ZN4IIIII4HHHHE4ffffEv.part.1

Symbol is named ...part.1 instead of ...part.2 in this case.

$ echo "int main() { return 0; }" | gcc -x c -c - -o main.o
$ g++ -o main main.o t1.o t2.o
`_ZN4IIIII4HHHHE4ffffEv.part.1' referenced in section `.text.unlikely' of t2.o: defined in discarded section `.text.unlikely._ZN4IIIII4HHHHE4ffffEv.part.1[_ZN4IIIII4HHHHE4ffffEv]' of t2.o
collect2: error: ld returned 1 exit status



Following works:
(1) gcc-5 and gcc-6
(2) gcc-7 with -O1
(3) marking ffff() with __attribute__((used))
    (found in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65199)
(4) patch binutils in file bfd/elflink.c, function _bfd_elf_default_action_discarded:
    remove the COMPLAIN flag


Nevertheless, it is probably a bug on gcc side, as in similar old bug 49665 with same linker error.
Comment 1 Martin Liška 2017-09-29 09:02:50 UTC
Created attachment 42259 [details]
Reduced single compilation unit test-case

Confirmed, following ICEs in GCC (with -fchecking):

g++-7 pr82352-2.cpp -O2 -c -fchecking
pr82352-2.cpp:42:7: warning: direct base ‘B’ inaccessible in ‘o’ due to ambiguity
 class o : B, n
       ^
pr82352-2.cpp:51:1: error: comdat-local function called by void h::i() outside its comdat
 }
 ^
_ZN1fI1oE1dEv.part.0/38 (void f<e>::d() [with e = o]) @0x149a95bd5450
  Type: function definition analyzed
  Visibility: comdat_group:_ZN1fI1oE1dEv artificial
  Same comdat group as: _ZN1fI1oE1dEv/26
  References: _ZTI1a/24 (addr)
  Referring: 
  Availability: local
  First run: 1
  Function flags: body local icf_merged split_part unlikely_executed
  Called by: _ZN1h1iEv.part.1/39 (1.00 per call) (can throw external) _ZN1fI1oE1dEv/26 (can throw external) 
  Calls: __cxa_allocate_exception/31 (1.00 per call) __cxa_throw/32 (1.00 per call) (can throw external) 
pr82352-2.cpp:51: confused by earlier errors, bailing out

Caused by my commit r246848.
Comment 2 Martin Liška 2018-01-03 10:12:19 UTC
Created attachment 43012 [details]
Untested patch

Can you please the patch for original test-case? Not the reduced one?
Comment 3 Martin Liška 2018-01-03 12:54:28 UTC
> Can you please the patch for original test-case? Not the reduced one?

Can you please test the patch for original test-case? Not the reduced one?
Comment 4 Martin Liška 2018-01-04 08:54:48 UTC
Author: marxin
Date: Thu Jan  4 08:54:17 2018
New Revision: 256226

URL: https://gcc.gnu.org/viewcvs?rev=256226&root=gcc&view=rev
Log:
Be careful about comdat boundary in ICF (PR ipa/82352).

2018-01-04  Martin Liska  <mliska@suse.cz>

	PR ipa/82352
	* ipa-icf.c (sem_function::merge): Do not cross comdat boundary.
2018-01-04  Martin Liska  <mliska@suse.cz>

	PR ipa/82352
	* g++.dg/ipa/pr82352.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/ipa/pr82352.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/ipa-icf.c
    trunk/gcc/testsuite/ChangeLog
Comment 5 Martin Liška 2018-01-04 08:56:04 UTC
Fixed on trunk.
Comment 6 Holger Hopp 2018-01-04 15:41:13 UTC
The patch fixes my >10 original issues with gcc-7.
It also fixes similar (other, fewer) issues with gcc-6 (gcc-6.2.1 was ok, gcc-6.3.1 not ok, with patch ok).
So please downport this patch also to gcc-6 branch.
Thanks!
Comment 7 Jakub Jelinek 2018-01-04 21:13:48 UTC
Author: jakub
Date: Thu Jan  4 21:13:17 2018
New Revision: 256266

URL: https://gcc.gnu.org/viewcvs?rev=256266&root=gcc&view=rev
Log:
	PR ipa/82352
	* g++.dg/ipa/pr82352.C (size_t): Define to __SIZE_TYPE__ instead of
	long unsigned int.

Modified:
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/ipa/pr82352.C
Comment 8 Martin Liška 2018-01-17 11:47:02 UTC
Author: marxin
Date: Wed Jan 17 11:46:31 2018
New Revision: 256789

URL: https://gcc.gnu.org/viewcvs?rev=256789&root=gcc&view=rev
Log:
Backport r256226

2018-01-17  Martin Liska  <mliska@suse.cz>

	Backport from mainline
	2018-01-04  Martin Liska  <mliska@suse.cz>

	PR ipa/82352
	* ipa-icf.c (sem_function::merge): Do not cross comdat boundary.
2018-01-17  Martin Liska  <mliska@suse.cz>

	Backport from mainline
	2018-01-04  Martin Liska  <mliska@suse.cz>

	PR ipa/82352
	* g++.dg/ipa/pr82352.C: New test.

Added:
    branches/gcc-7-branch/gcc/testsuite/g++.dg/ipa/pr82352.C
Modified:
    branches/gcc-7-branch/gcc/ChangeLog
    branches/gcc-7-branch/gcc/ipa-icf.c
    branches/gcc-7-branch/gcc/testsuite/ChangeLog
Comment 9 Martin Liška 2018-01-17 11:47:27 UTC
Author: marxin
Date: Wed Jan 17 11:46:56 2018
New Revision: 256790

URL: https://gcc.gnu.org/viewcvs?rev=256790&root=gcc&view=rev
Log:
Backport r256266

2018-01-17  Martin Liska  <mliska@suse.cz>

	Backport from mainline
	2018-01-04  Jakub Jelinek  <jakub@redhat.com>

	PR ipa/82352
	* g++.dg/ipa/pr82352.C (size_t): Define to __SIZE_TYPE__ instead of
	long unsigned int.

Modified:
    branches/gcc-7-branch/gcc/testsuite/ChangeLog
    branches/gcc-7-branch/gcc/testsuite/g++.dg/ipa/pr82352.C
Comment 10 Martin Liška 2018-01-17 11:48:29 UTC
Fixed on GCC-7 branch.
Comment 11 Martin Liška 2018-03-08 08:56:51 UTC
Author: marxin
Date: Thu Mar  8 08:56:20 2018
New Revision: 258358

URL: https://gcc.gnu.org/viewcvs?rev=258358&root=gcc&view=rev
Log:
Backport r256226

2018-03-08  Martin Liska  <mliska@suse.cz>

	Backport from mainline
	2018-01-04  Martin Liska  <mliska@suse.cz>

	PR ipa/82352
	* ipa-icf.c (sem_function::merge): Do not cross comdat boundary.
2018-03-08  Martin Liska  <mliska@suse.cz>

	Backport from mainline
	2018-01-04  Martin Liska  <mliska@suse.cz>

	PR ipa/82352
	* g++.dg/ipa/pr82352.C: New test.

Added:
    branches/gcc-6-branch/gcc/testsuite/g++.dg/ipa/pr82352.C
Modified:
    branches/gcc-6-branch/gcc/ChangeLog
    branches/gcc-6-branch/gcc/ipa-icf.c
    branches/gcc-6-branch/gcc/testsuite/ChangeLog
Comment 12 bin cheng 2018-03-09 09:42:38 UTC
(In reply to Martin Liška from comment #11)
> Author: marxin
> Date: Thu Mar  8 08:56:20 2018
> New Revision: 258358
> 
> URL: https://gcc.gnu.org/viewcvs?rev=258358&root=gcc&view=rev
> Log:
> Backport r256226
> 
> 2018-03-08  Martin Liska  <mliska@suse.cz>
> 
> 	Backport from mainline
> 	2018-01-04  Martin Liska  <mliska@suse.cz>
> 
> 	PR ipa/82352
> 	* ipa-icf.c (sem_function::merge): Do not cross comdat boundary.
> 2018-03-08  Martin Liska  <mliska@suse.cz>
> 
> 	Backport from mainline
> 	2018-01-04  Martin Liska  <mliska@suse.cz>
> 
> 	PR ipa/82352
> 	* g++.dg/ipa/pr82352.C: New test.
> 
> Added:
>     branches/gcc-6-branch/gcc/testsuite/g++.dg/ipa/pr82352.C
> Modified:
>     branches/gcc-6-branch/gcc/ChangeLog
>     branches/gcc-6-branch/gcc/ipa-icf.c
>     branches/gcc-6-branch/gcc/testsuite/ChangeLog

Hi Martin,
The backported test failed on arm-none-eabi and arm-none-linux-gnueabihf with below message:

/tmp/build/src/gcc/gcc/testsuite/g++.dg/ipa/pr82352.C:20:30: error: 'operator new' takes type 'size_t' ('unsigned int') as first parameter [-fpermissive]
Comment 13 hjl@gcc.gnu.org 2018-03-10 18:46:26 UTC
Author: hjl
Date: Sat Mar 10 18:45:55 2018
New Revision: 258418

URL: https://gcc.gnu.org/viewcvs?rev=258418&root=gcc&view=rev
Log:
Backport r256266 from mainline

	Backport from mainline
	2018-01-04  Jakub Jelinek  <jakub@redhat.com>

	PR ipa/82352
	* g++.dg/ipa/pr82352.C (size_t): Define to __SIZE_TYPE__ instead of
	long unsigned int.

Modified:
    branches/gcc-6-branch/gcc/testsuite/ChangeLog
    branches/gcc-6-branch/gcc/testsuite/g++.dg/ipa/pr82352.C