Message ID | 20151214180811.GG3956@virgil.suse.cz |
---|---|
State | New |
Headers | show |
> Hi, > > in PR 68851, IPA-CP decides to clone for all known contexts, even when > it is not local because the code is not supposed to grow anyway. The > code doing that uses collect_callers method of cgraph_edge to find all > the edges which are to be redirected in such case. However, there is > also an edge from a hunk to the cloned node and that gets collected > and redirected too. Later on, this inconsistency (a thunk calling a > wrong node) leads to an assert in comdat handling, but it can lead to > all sorts of trouble. > > The following patch fixes it by checking that thunks are not added > into the vector in that method (which is only used by IPA-CP at this > one spot and IPA-SRA so it should be fine). Bootstrapped and tested > on x86_64-linux. OK for trunk? And perhaps for the gcc-5 branch too? > > Thanks, > > Martin > > > 2015-12-14 Martin Jambor <mjambor@suse.cz> > > PR ipa/68851 > * cgraph.c (collect_callers_of_node_1): Do not collect thunks. > * cgraph.h (cgraph_node): Change comment of collect_callers. > > testsuite/ > * g++.dg/ipa/pr68851.C: New test. This is OK (for branches too if it won't cause issues for a week) thanks! Honza
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index c8c3370..5a9c2a2 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2592,7 +2592,8 @@ collect_callers_of_node_1 (cgraph_node *node, void *data) if (avail > AVAIL_INTERPOSABLE) for (cs = node->callers; cs != NULL; cs = cs->next_caller) - if (!cs->indirect_inlining_edge) + if (!cs->indirect_inlining_edge + && !cs->caller->thunk.thunk_p) redirect_callers->safe_push (cs); return false; } diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 0a09391..ba14215 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1070,7 +1070,7 @@ public: cgraph_edge *get_edge (gimple *call_stmt); /* Collect all callers of cgraph_node and its aliases that are known to lead - to NODE (i.e. are not overwritable). */ + to NODE (i.e. are not overwritable) and that are not thunks. */ vec<cgraph_edge *> collect_callers (void); /* Remove all callers from the node. */ diff --git a/gcc/testsuite/g++.dg/ipa/pr68851.C b/gcc/testsuite/g++.dg/ipa/pr68851.C new file mode 100644 index 0000000..659e4cd --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr68851.C @@ -0,0 +1,29 @@ +// { dg-do compile } +// { dg-options "-O3" } + +class A; +class B { +public: + operator A *() const; +}; +class A { +public: + virtual bool isFormControlElement() const {} +}; +class C { + struct D { + B element; + }; + bool checkPseudoClass(const D &, int &) const; +}; +class F { + virtual bool isFormControlElement() const; +}; +class G : A, F { + bool isFormControlElement() const {} +}; +bool C::checkPseudoClass(const D &p1, int &) const { + A &a = *p1.element; + a.isFormControlElement(); + a.isFormControlElement() || a.isFormControlElement(); +}