1 // { dg-do compile }
2 // { dg-options "-std=c++17" }
3 
4 // Check that we can fold over all of the operators required
5 // by the standard in every possible way.
6 
7 #define COMMA ,
8 
9 #define MAKE_FNS(name, op) \
10   template<typename... Ts> \
11     auto unary_left_ ## name (Ts... ts) { return (... op ts); } \
12   template<typename... Ts> \
13     auto unary_right_ ## name (Ts... ts) { return (ts op ...); } \
14   template<typename T, typename... Ts> \
15     auto binary_left_ ## name (T x, Ts... ts) { return (x op ... op ts); } \
16   template<typename T, typename... Ts> \
17     auto binary_right_ ## name (T x, Ts... ts) { return (ts op ... op x); }
18 
19 // TODO: These are compile-only tests...
20 #define CHECK_FN(name) \
21   unary_left_ ## name (a); \
22   unary_left_ ## name (a, b, c); \
23   unary_right_ ## name (a); \
24   unary_right_ ## name (a, b, c); \
25   binary_left_ ## name (a); \
26   binary_left_ ## name (a, b, c, d); \
27   binary_right_ ## name (d); \
28   binary_right_ ## name (d, a, b, c);
29 
30 MAKE_FNS (add, +);
31 MAKE_FNS (sub, -);
32 MAKE_FNS (mul, *);
33 MAKE_FNS (div, /);
34 MAKE_FNS (mod, %);
35 MAKE_FNS (bxor, ^);
36 MAKE_FNS (bor, |);
37 MAKE_FNS (band, &);
38 MAKE_FNS (lsh, <<);
39 MAKE_FNS (rsh, >>);
40 
41 MAKE_FNS (assign, =);
42 MAKE_FNS (addi, +=);
43 MAKE_FNS (subi, -=);
44 MAKE_FNS (muli, *=);
45 MAKE_FNS (divi, /=);
46 MAKE_FNS (modi, %=);
47 MAKE_FNS (bxori, ^=);
48 MAKE_FNS (bori, |=);
49 MAKE_FNS (bandi, &=);
50 MAKE_FNS (lshi, <<=);
51 MAKE_FNS (rshi, >>=);
52 
53 MAKE_FNS (eq, ==);
54 MAKE_FNS (ne, !=);
55 MAKE_FNS (lt, <);
56 MAKE_FNS (gt, >);
57 MAKE_FNS (le, <=);
58 MAKE_FNS (ge, >=);
59 
60 MAKE_FNS (land, &&);
61 MAKE_FNS (lor, ||);
62 
63 MAKE_FNS (comma, COMMA);
64 MAKE_FNS (dot_star, .*);
65 MAKE_FNS (arrow_star, ->*);
66 
main()67 int main() {
68   int a = 0, b = 0, c = 0, d = 0;
69 
70   CHECK_FN (add);
71   CHECK_FN (sub);
72   CHECK_FN (mul);
73   CHECK_FN (div);
74   CHECK_FN (mod);
75   CHECK_FN (bxor);
76   CHECK_FN (bor);
77   CHECK_FN (band);
78   CHECK_FN (lsh);
79   CHECK_FN (rsh);
80 
81   // CHECK_FN (assign);
82   CHECK_FN (addi);
83   CHECK_FN (subi);
84   CHECK_FN (muli);
85   CHECK_FN (divi);
86   CHECK_FN (modi);
87   CHECK_FN (bxori);
88   CHECK_FN (bori);
89   CHECK_FN (bandi);
90   CHECK_FN (lshi);
91   CHECK_FN (rshi);
92 
93   CHECK_FN (eq);
94   CHECK_FN (ne);
95   CHECK_FN (lt);
96   CHECK_FN (gt);
97   CHECK_FN (le);
98   CHECK_FN (ge);
99   CHECK_FN (eq);
100   CHECK_FN (ne);
101 
102   CHECK_FN (comma);
103 
104   struct X {
105     int a;
106   } x, *px = &x;
107 
108   int X::* pm = &X::a;
109   unary_left_arrow_star (px, pm); // px ->* pm
110   unary_right_arrow_star (px, pm); // px ->* pm
111   binary_left_arrow_star (px, pm); // px ->* pm
112   binary_right_arrow_star (pm, px); // px ->* pm
113 
114   unary_left_dot_star (x, pm); // x ->* pm
115   unary_right_dot_star (x, pm); // x ->* pm
116   binary_left_dot_star (x, pm); // x ->* pm
117   binary_right_dot_star (pm, x); // x ->* pm
118 }
119