// PR c++/37016
|
// PR c++/37016
|
// { dg-do run }
|
// { dg-do run }
|
// { dg-options "-O2 -Wall" }
|
// { dg-options "-O2 -Wall" }
|
|
|
/*
|
/*
|
Basic design concept is that WorldObject implements remote method call
|
Basic design concept is that WorldObject implements remote method call
|
functionality using the "curiously recurring template pattern" to enable
|
functionality using the "curiously recurring template pattern" to enable
|
forwarding calls from the generic base class that implements the transport
|
forwarding calls from the generic base class that implements the transport
|
layer to the derived class.
|
layer to the derived class.
|
|
|
The specific failure was in forwarding calls to items in a container.
|
The specific failure was in forwarding calls to items in a container.
|
This is emulated here by wrapping a single item.
|
This is emulated here by wrapping a single item.
|
|
|
In the main program there are two forms of the call. In the last
|
In the main program there are two forms of the call. In the last
|
(uncommented) form the member function pointer is for clarity
|
(uncommented) form the member function pointer is for clarity
|
assigned to a variable (itemfunptr) before making the call.
|
assigned to a variable (itemfunptr) before making the call.
|
With 4.3.0 and 4.3.1 this code compiles incorrectly with -O1 or greater
|
With 4.3.0 and 4.3.1 this code compiles incorrectly with -O1 or greater
|
to produce this warning
|
to produce this warning
|
|
|
reproduce.cc: In function ‘int main()’:
|
reproduce.cc: In function ‘int main()’:
|
reproduce.cc:26: warning: ‘itemfunptr.void (Container::*)(void
|
reproduce.cc:26: warning: ‘itemfunptr.void (Container::*)(void
|
(Item::*)(int), int)::__pfn’ is used uninitialized in this function
|
(Item::*)(int), int)::__pfn’ is used uninitialized in this function
|
reproduce.cc:47: note: ‘itemfunptr.void (Container::*)(void (Item::*)(int),
|
reproduce.cc:47: note: ‘itemfunptr.void (Container::*)(void (Item::*)(int),
|
int)::__pfn’ was declared here
|
int)::__pfn’ was declared here
|
|
|
and the resulting executable segvs. It works correctly with -O0.
|
and the resulting executable segvs. It works correctly with -O0.
|
|
|
With 4.2.3 and earlier it works correctly with optimization.
|
With 4.2.3 and earlier it works correctly with optimization.
|
|
|
In the first (commented out) form of the call in the main program
|
In the first (commented out) form of the call in the main program
|
we directly refer to desired member function. This compiles
|
we directly refer to desired member function. This compiles
|
and executes correctly with all tested versions.
|
and executes correctly with all tested versions.
|
*/
|
*/
|
|
|
extern "C" int printf (const char *, ...);
|
extern "C" int printf (const char *, ...);
|
|
|
template
|
template
|
struct WorldObject {
|
struct WorldObject {
|
template
|
template
|
void forward(memfunT memfun, arg1T arg1, arg2T arg2) {
|
void forward(memfunT memfun, arg1T arg1, arg2T arg2) {
|
Derived* obj = static_cast(this);
|
Derived* obj = static_cast(this);
|
(obj->*memfun)(arg1, arg2);
|
(obj->*memfun)(arg1, arg2);
|
}
|
}
|
};
|
};
|
|
|
struct Item {
|
struct Item {
|
void fred(int a) {
|
void fred(int a) {
|
printf ("a=%d\n", a);
|
printf ("a=%d\n", a);
|
}
|
}
|
};
|
};
|
|
|
struct Container : public WorldObject {
|
struct Container : public WorldObject {
|
Item item;
|
Item item;
|
template
|
template
|
void itemfun(itemfunT itemfun, int a) {
|
void itemfun(itemfunT itemfun, int a) {
|
(item.*itemfun)(a);
|
(item.*itemfun)(a);
|
}
|
}
|
};
|
};
|
|
|
int main() {
|
int main() {
|
typedef void (Item::*itemfun)(int);
|
typedef void (Item::*itemfun)(int);
|
|
|
Container t;
|
Container t;
|
|
|
// This call compiles and executes correctly with all versions tested
|
// This call compiles and executes correctly with all versions tested
|
//t.forward(&Container::itemfun, &Item::fred, 1);
|
//t.forward(&Container::itemfun, &Item::fred, 1);
|
|
|
// This call compiles with a warning and segvs on execution if using
|
// This call compiles with a warning and segvs on execution if using
|
// -O1 or greater with 4.3.*. 4.2.* is correct.
|
// -O1 or greater with 4.3.*. 4.2.* is correct.
|
void (Container::*itemfunptr)(itemfun, int) =
|
void (Container::*itemfunptr)(itemfun, int) =
|
&Container::itemfun;
|
&Container::itemfun;
|
t.forward(itemfunptr, &Item::fred, 1);
|
t.forward(itemfunptr, &Item::fred, 1);
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
|