1 // PR c++/91361 - P1152R4: Deprecating some uses of volatile.
2 // { dg-do compile { target c++17 } }
3 
4 #define ACCESS_ONCE(x) (*(volatile __typeof(x) *)&(x))
5 
6 struct S {
7   volatile int a : 4;
8   int b : 2;
9 };
10 
11 struct T {
12   int a : 4;
13   int b : 2;
14 };
15 
16 union U {
17   char c;
18   int i;
19 };
20 
21 struct W {
22   W();
23   W(volatile W&);
24   W& operator=(volatile W&) volatile;
25 };
26 
27 volatile int // { dg-warning ".volatile.-qualified return type is deprecated" "" { target c++20 } }
fn(volatile int i)28 fn (volatile int i) // { dg-warning ".volatile.-qualified parameter is deprecated" "" { target c++20 } }
29 {
30   volatile int v = 10;
31   int *volatile p = nullptr;
32 
33   // Pre/post ++/--.
34   v++; // { dg-warning "expression of .volatile.-qualified type is deprecated" "" { target c++20 } }
35   ++v; // { dg-warning "expression of .volatile.-qualified type is deprecated" "" { target c++20 } }
36   v--; // { dg-warning "expression of .volatile.-qualified type is deprecated" "" { target c++20 } }
37   --v; // { dg-warning "expression of .volatile.-qualified type is deprecated" "" { target c++20 } }
38   p++; // { dg-warning "expression of .volatile.-qualified type is deprecated" "" { target c++20 } }
39   ++p; // { dg-warning "expression of .volatile.-qualified type is deprecated" "" { target c++20 } }
40   p--; // { dg-warning "expression of .volatile.-qualified type is deprecated" "" { target c++20 } }
41   --p; // { dg-warning "expression of .volatile.-qualified type is deprecated" "" { target c++20 } }
42   return v + i + *p;
43 }
44 
45 void
fn2()46 fn2 ()
47 {
48   volatile int vi = 42;
49   int i = 24;
50 
51   // Discarded-value expression ([expr.context]).
52   // The lvalue-to-rvalue conversion is applied here:
53   vi;
54   // ...but not here.  Otherwise we'd write to VI and then immediately read it.
55   vi = 42;
56   vi = i;
57   vi = i = 42;
58   i = vi = 42; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
59   &(vi = i); // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
60   (vi = 42, 45);
61   (i = vi = 42, 10); // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
62   i = vi; // LHS not volatile.
63   i = (vi = i, 42);
64   static_cast<void>(vi = i);
65   static_cast<void>(i = vi = 42); // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
66   (void)(vi = i);
67   (void)(i = vi = 42); // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
68 
69   // Unevaluated operand.
70   decltype(vi = 42) x = vi;
71   decltype(i = vi = 42) x3 = i;
72 
73   // Compound assignments.
74   vi += i; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
75   vi -= i; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
76   vi %= i; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
77   vi ^= i; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
78   vi |= i; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
79   vi /= i; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
80   vi = vi += 42; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
81   vi += vi = 42; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
82   i *= vi;
83   decltype(vi -= 42) x2 = vi; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
84 
85   // Structured bindings.
86   int a[] = { 10, 5 };
87   const auto & [cxr, cyr] = a;
88   const volatile auto & [cvxr, cvyr] = a; // { dg-warning ".volatile.-qualified structured binding is deprecated" "" { target c++20 } }
89   volatile auto & [vxr, vyr] = a; // { dg-warning ".volatile.-qualified structured binding is deprecated" "" { target c++20 } }
90 }
91 
92 void
fn3()93 fn3 ()
94 {
95   volatile int i, j, k = 0;
96   i = j = k; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
97 
98   ACCESS_ONCE(j);
99 
100   S s;
101   s.b = 1;
102 
103   volatile U u;
104   u.c = 42;
105   i = u.c = 42; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
106   u.c += 42; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
107 
108   volatile T t;
109   t.a = 3;
110   j = t.a = 3; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
111   t.a += 3; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
112 
113   volatile int *src = &i;
114   *src; // No assignment, don't warn.
115 }
116 
117 void
fn4()118 fn4 ()
119 {
120   volatile W vw;
121   W w;
122   // Assignment to objects of a class is defined by the copy/move assignment
123   // operator.
124   vw = w;
125   w = vw;
126 }
127 
128 template<typename T>
raccoon()129 void raccoon ()
130 {
131   volatile T t, u;
132   t = 42;
133   u = t = 42; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
134   t &= 42; // { dg-warning "assignment with .volatile.-qualified left operand is deprecated" "" { target c++20 } }
135 }
136 
137 void
fn5()138 fn5 ()
139 {
140   raccoon<int>();
141 }
142