blob: 92526b5058bd6e3c70a4ca0cd7e7d0c690018336 [file] [log] [blame]
// PR c++/91361 - P1152R4: Deprecating some uses of volatile.
// { dg-do compile { target c++20 } }
// { dg-options "-Wno-volatile" }
#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<void>(vi = i);
static_cast<void>(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<typename T>
void raccoon ()
{
volatile T t, u;
t = 42;
u = t = 42;
t &= 42;
}
void
fn5 ()
{
raccoon<int>();
}