// PR c++/91361 - P1152R4: Deprecating some uses of volatile. // { dg-do compile { target c++2a } } // { dg-options "-Wno-deprecated" } #define ACCESS_ONCE(x) (*(volatile __typeof(x) *)&(x)) struct S { volatile int a : 4; int b : 2; }; struct T { int a : 4; int b : 2; }; union U { char c; int i; }; struct W { W(); W(volatile W&); W& operator=(volatile W&) volatile; }; volatile int fn (volatile int i) { volatile int v = 10; int *volatile p = nullptr; // Pre/post ++/--. v++; ++v; v--; --v; p++; ++p; p--; --p; return v + i + *p; } void fn2 () { volatile int vi = 42; int i = 24; // Discarded-value expression ([expr.context]). // The lvalue-to-rvalue conversion is applied here: vi; // ...but not here. Otherwise we'd write to VI and then immediately read it. vi = 42; vi = i; vi = i = 42; i = vi = 42; &(vi = i); (vi = 42, 45); (i = vi = 42, 10); i = vi; // LHS not volatile. i = (vi = i, 42); static_cast(vi = i); static_cast(i = vi = 42); (void)(vi = i); (void)(i = vi = 42); // Unevaluated operand. decltype(vi = 42) x = vi; decltype(i = vi = 42) x3 = i; // Compound assignments. vi += i; vi -= i; vi %= i; vi ^= i; vi |= i; vi /= i; vi = vi += 42; vi += vi = 42; i *= vi; decltype(vi -= 42) x2 = vi; // Structured bindings. int a[] = { 10, 5 }; const auto & [cxr, cyr] = a; const volatile auto & [cvxr, cvyr] = a; volatile auto & [vxr, vyr] = a; } void fn3 () { volatile int i, j, k = 0; i = j = k; ACCESS_ONCE(j); S s; s.b = 1; volatile U u; u.c = 42; i = u.c = 42; u.c += 42; volatile T t; t.a = 3; j = t.a = 3; t.a += 3; volatile int *src = &i; *src; // No assignment, don't warn. } void fn4 () { volatile W vw; W w; // Assignment to objects of a class is defined by the copy/move assignment // operator. vw = w; w = vw; } template void raccoon () { volatile T t, u; t = 42; u = t = 42; t &= 42; } void fn5 () { raccoon(); }