1 // P0145R2: Refining Expression Order for C++
2 // { dg-do run }
3 // { dg-options "-std=c++17" }
4 
5 extern "C" int printf (const char *, ...);
sink(...)6 void sink(...) { }
7 
8 int last = 0;
f(int i)9 int f(int i)
10 {
11   if (i < last)
12     __builtin_abort ();
13   last = i;
14   return i;
15 }
16 
g(int i)17 int& g(int i)
18 {
19   static int dummy;
20   f(i);
21   return dummy;
22 }
23 
24 struct A
25 {
26   int _i;
AA27   A(int i): _i(f(i)) { }
memfnA28   A& memfn(int i, int j) { f(j); return *this; }
29   int operator<<(int i) { return 0; }
30   A& operator=(const A&) { return *this; }
31   A& operator+=(int i) { return *this; }
32 };
33 
34 struct B
35 {
36   int _i;
BB37   B(): _i(0) {}
BB38   B(int i): _i(f(i)) { }
39 };
40 
41 int operator>>(A&, int i) { return 0; }
42 
43 A a(0);
afn(int i)44 A* afn(int i)
45 {
46   f(i);
47   return &a;
48 }
49 
aref(int i)50 A& aref(int i)
51 {
52   f(i);
53   return a;
54 }
55 
56 B b;
bval(int i)57 B bval(int i)
58 {
59   return B(i);
60 }
61 
bref(int i)62 B& bref(int i)
63 {
64   f(i);
65   return b;
66 }
67 
68 static int si;
ip(int i)69 int* ip (int i)
70 {
71   f(i);
72   return &si;
73 }
74 
iref(int i)75 int& iref(int i)
76 {
77   f(i);
78   return si;
79 }
80 
pmff(int i)81 auto pmff(int i) {
82   f(i);
83   return &A::memfn;
84 }
85 
f()86 template <class T> void f()
87 {
88   // a.b
89   A(1).memfn(f(2),3).memfn(f(4),5);
90   aref(6).memfn(f(7),8);
91   (aref(9).*pmff(10))(f(11),12);
92   last = 0;
93 
94   // a->b
95   afn(12)->memfn(f(13),14);
96 
97   // a->*b
98   (afn(15)->*pmff(16))(f(17),18);
99   last = 0;
100 
101   // a(b)
102   // covered in eval-order1.C
103 
104   // b @= a
105   aref(19)=A(18);
106   iref(21)=f(20);
107   aref(23)+=f(22);
108   bref(25)=bval(24);
109   (f(27), b) = bval(26);
110   last = 0;
111 
112   int ar[4] = {};
113   int i = 0;
114   ar[i++] = i;
115   if (ar[0] != 0)
116     __builtin_abort();
117 
118   // a[b]
119   afn(20)[f(21)-21].memfn(f(22),23);
120   ip(24)[f(25)-25] = 0;
121   last=0;
122 
123   // a << b
124   aref(24) << f(25);
125   iref(26) << f(27);
126   last=0;
127 
128   // a >> b
129   aref(26) >> f(27);
130   iref(28) >> f(29);
131 }
132 
g()133 void g()
134 {
135   // a.b
136   A(1).memfn(f(2),3).memfn(f(4),5);
137   aref(6).memfn(f(7),8);
138   (aref(9).*pmff(10))(f(11),12);
139   last = 0;
140 
141   // a->b
142   afn(12)->memfn(f(13),14);
143 
144   // a->*b
145   (afn(15)->*pmff(16))(f(17),18);
146   last = 0;
147 
148   // a(b)
149   // covered in eval-order1.C
150 
151   // b @= a
152   aref(19)=A(18);
153   iref(21)=f(20);
154   aref(23)+=f(22);
155   bref(25)=bval(24);
156   (f(27), b) = bval(26);
157   last = 0;
158 
159   int ar[4] = {};
160   int i = 0;
161   ar[i++] = i;
162   if (ar[0] != 0)
163     __builtin_abort();
164 
165   // a[b]
166   afn(20)[f(21)-21].memfn(f(22),23);
167   ip(24)[f(25)-25] = 0;
168   last=0;
169 
170   // a << b
171   aref(24) << f(25);
172   iref(26) << f(27);
173   last=0;
174 
175   // a >> b
176   aref(26) >> f(27);
177   iref(28) >> f(29);
178 }
179 
main()180 int main()
181 {
182   g();
183   last = 0;
184   f<int>();
185 }
186