111
|
1 // PR c++/37016
|
|
2 // { dg-do run }
|
|
3 // { dg-options "-O2 -Wall" }
|
|
4
|
|
5 /*
|
|
6 Basic design concept is that WorldObject implements remote method call
|
|
7 functionality using the "curiously recurring template pattern" to enable
|
|
8 forwarding calls from the generic base class that implements the transport
|
|
9 layer to the derived class.
|
|
10
|
|
11 The specific failure was in forwarding calls to items in a container.
|
|
12 This is emulated here by wrapping a single item.
|
|
13
|
|
14 In the main program there are two forms of the call. In the last
|
|
15 (uncommented) form the member function pointer is for clarity
|
|
16 assigned to a variable (itemfunptr) before making the call.
|
|
17 With 4.3.0 and 4.3.1 this code compiles incorrectly with -O1 or greater
|
|
18 to produce this warning
|
|
19
|
|
20 reproduce.cc: In function ‘int main()’:
|
|
21 reproduce.cc:26: warning: ‘itemfunptr.void (Container::*)(void
|
|
22 (Item::*)(int), int)::__pfn’ is used uninitialized in this function
|
|
23 reproduce.cc:47: note: ‘itemfunptr.void (Container::*)(void (Item::*)(int),
|
|
24 int)::__pfn’ was declared here
|
|
25
|
|
26 and the resulting executable segvs. It works correctly with -O0.
|
|
27
|
|
28 With 4.2.3 and earlier it works correctly with optimization.
|
|
29
|
|
30 In the first (commented out) form of the call in the main program
|
|
31 we directly refer to desired member function. This compiles
|
|
32 and executes correctly with all tested versions.
|
|
33 */
|
|
34
|
|
35 extern "C" int printf (const char *, ...);
|
|
36
|
|
37 template <class Derived>
|
|
38 struct WorldObject {
|
|
39 template <typename memfunT, typename arg1T, typename arg2T>
|
|
40 void forward(memfunT memfun, arg1T arg1, arg2T arg2) {
|
|
41 Derived* obj = static_cast<Derived*>(this);
|
|
42 (obj->*memfun)(arg1, arg2);
|
|
43 }
|
|
44 };
|
|
45
|
|
46 struct Item {
|
|
47 void fred(int a) {
|
|
48 printf ("a=%d\n", a);
|
|
49 }
|
|
50 };
|
|
51
|
|
52 struct Container : public WorldObject<Container> {
|
|
53 Item item;
|
|
54 template <typename itemfunT, typename arg1T>
|
|
55 void itemfun(itemfunT itemfun, int a) {
|
|
56 (item.*itemfun)(a);
|
|
57 }
|
|
58 };
|
|
59
|
|
60 int main() {
|
|
61 typedef void (Item::*itemfun)(int);
|
|
62
|
|
63 Container t;
|
|
64
|
|
65 // This call compiles and executes correctly with all versions tested
|
|
66 //t.forward(&Container::itemfun<itemfun,int>, &Item::fred, 1);
|
|
67
|
|
68 // This call compiles with a warning and segvs on execution if using
|
|
69 // -O1 or greater with 4.3.*. 4.2.* is correct.
|
|
70 void (Container::*itemfunptr)(itemfun, int) =
|
|
71 &Container::itemfun<itemfun,int>;
|
|
72 t.forward(itemfunptr, &Item::fred, 1);
|
|
73
|
|
74 return 0;
|
|
75 }
|
|
76
|