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