Fix cgraph_node::function_symbol availability compuattion [PR94202]

this fixes ICE in inliner cache sanity check which is caused by very old
bug in visibility calculation in cgraph_node::function_symbol and
cgraph_node::function_or_virtual_thunk_symbol.

In the testcase there is indirect call to a thunk. At begining we correctly
see that its body as AVAIL_AVAILABLE but later we inline into the thunk and
this turns it to AVAIL_INTERPOSABLE.

This is because function_symbol incorrectly overwrites availability parameter
by availability of the alias used in the call within thunk, which is a local
alias.

gcc/ChangeLog:

2020-03-19  Jan Hubicka  <hubicka@ucw.cz>

	PR ipa/94202
	* cgraph.c (cgraph_node::function_symbol): Fix availability computation.
	(cgraph_node::function_or_virtual_thunk_symbol): Likewise.

gcc/testsuite/ChangeLog:

2020-03-19  Jan Hubicka  <hubicka@ucw.cz>

	PR ipa/94202
	* g++.dg/torture/pr94202.C: New test.
This commit is contained in:
Jan Hubicka 2020-03-20 00:42:13 +01:00
parent 9def91e9f2
commit f7dceb4e65
4 changed files with 43 additions and 16 deletions

View file

@ -1,3 +1,9 @@
2020-03-19 Jan Hubicka <hubicka@ucw.cz>
PR ipa/94202
* cgraph.c (cgraph_node::function_symbol): Fix availability computation.
(cgraph_node::function_or_virtual_thunk_symbol): Likewise.
2020-03-19 Jan Hubicka <hubicka@ucw.cz>
PR ipa/92372

View file

@ -3788,16 +3788,13 @@ cgraph_node::function_symbol (enum availability *availability,
while (node->thunk.thunk_p)
{
enum availability a;
ref = node;
node = node->callees->callee;
if (availability)
{
enum availability a;
a = node->get_availability (ref);
if (a < *availability)
*availability = a;
}
node = node->ultimate_alias_target (availability, ref);
node = node->ultimate_alias_target (availability ? &a : NULL, ref);
if (availability && a < *availability)
*availability = a;
}
return node;
}
@ -3818,16 +3815,13 @@ cgraph_node::function_or_virtual_thunk_symbol
while (node->thunk.thunk_p && !node->thunk.virtual_offset_p)
{
enum availability a;
ref = node;
node = node->callees->callee;
if (availability)
{
enum availability a;
a = node->get_availability (ref);
if (a < *availability)
*availability = a;
}
node = node->ultimate_alias_target (availability, ref);
node = node->ultimate_alias_target (availability ? &a : NULL, ref);
if (availability && a < *availability)
*availability = a;
}
return node;
}

View file

@ -1,3 +1,8 @@
2020-03-19 Jan Hubicka <hubicka@ucw.cz>
PR ipa/94202
* g++.dg/torture/pr94202.C: New test.
2020-03-19 Jakub Jelinek <jakub@redhat.com>
PR gcov-profile/94029

View file

@ -0,0 +1,22 @@
// { dg-additional-options "-w" }
struct S1 {
virtual ~S1();
virtual void v();
};
struct S2: S1 {};
struct S3: S1, S2 { void v(); };
struct S4: S3 { void v(); };
void S4::v() { S3::v(); }
struct R {
S1 * m;
void f(S2 * x) {
static_cast<S1 *>(x)->v();
x->v();
m = x;
}
};
void f() {
R r;
r.f(new S4);
r.f(new S3);
}