===================================================================
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+struct A {
+ void operator==(const A &);
+};
+class B {
+public:
+ A m_fn1();
+ A m_fn2();
+};
+template <typename T, typename M> class C {
+public:
+ T Key;
+ const M &m_fn2(const T &);
+ virtual void m_fn1() {}
+ B _map;
+};
+
+C<int, int> b;
+template <typename T, typename M> const M &C<T, M>::m_fn2(const T &) {
+ A a = _map.m_fn2();
+ a == _map.m_fn1();
+ m_fn1();
+}
+
+void fn1() { b.m_fn2(0); }
And code in question:
;; Function const M& C<T, M>::m_fn2(const T&) [with T = int; M = int] (_ZN1CIiiE5m_fn2ERKi.isra.0, funcdef_no=10, decl_uid=2371, symbol_order=19)
const M& C<T, M>::m_fn2(const T&) [with T = int; M = int] (struct C * const this)
{
struct A D.2376;
struct A a;
struct B * _2;
int (*__vtbl_ptr_type) () * _3;
int (*__vtbl_ptr_type) () _4;
<bb 2>:
_2 = &this_1(D)->_map;
B::m_fn2 (_2);
B::m_fn1 (_2);
A::operator== (&a, &D.2376);
D.2376 ={v} {CLOBBER};
_3 = this_1(D)->_vptr.C;
_4 = *_3;
OBJ_TYPE_REF(_4;(struct C)this_1(D)->0) (this_1(D));
a ={v} {CLOBBER};
return;
}
Where this is propagated into &b that is a static variable of given type.
The reason why ipa-cp does not match is that it thinks the type may
dynamically change. I think it can not since the function is method and
I do not think methods except for ctors/dtors should have way to change
type of their object. Martin, Jason, is there way to implement this logic
into detect_type_change?
In any case the stopper here is:
D.2376 ={v} {CLOBBER};
that is stupid. I am testing followup patch that makes type change machinery
to walk through clobbers.
Bootstrapped/regtested x86_64-linux, will commit it shortly.
Honza
* cgraphclones.c (cgraph_clone_edge): Do not resolve speculative edges.
===================================================================
@@ -123,7 +123,10 @@ cgraph_clone_edge (struct cgraph_edge *e
{
tree decl;
- if (call_stmt && (decl = gimple_call_fndecl (call_stmt)))
+ if (call_stmt && (decl = gimple_call_fndecl (call_stmt))
+ /* When the call is speculative, we need to resolve it
+ via cgraph_resolve_speculation and not here. */
+ && !e->speculative)
{
struct cgraph_node *callee = cgraph_get_node (decl);
gcc_checking_assert (callee);