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