OK.
On Wed, Aug 28, 2019 at 7:56 PM Marek Polacek <pola...@redhat.com> wrote: > > On Wed, Aug 28, 2019 at 04:08:39PM -0400, Jason Merrill wrote: > > On 8/26/19 1:46 PM, Marek Polacek wrote: > > > +Wvolatile > > > +C++ ObjC++ Var(warn_volatile) Warning > > > +Warn about certain uses of volatile qualifier. > > > > Maybe "deprecated uses"? > > Ok, changed. > > > > --- gcc/cp/expr.c > > > +++ gcc/cp/expr.c > > > @@ -207,6 +207,27 @@ mark_use (tree expr, bool rvalue_p, bool read_p, > > > recurse_op[0] = true; > > > break; > > > + case MODIFY_EXPR: > > > + { > > > + tree lhs = TREE_OPERAND (expr, 0); > > > + /* [expr.ass] "A simple assignment whose left operand is of > > > + a volatile-qualified type is deprecated unless the assignment > > > + is either a discarded-value expression or appears in an > > > + unevaluated context." */ > > > + if (read_p > > > + && (TREE_THIS_VOLATILE (lhs) > > > + || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs))) > > > + && !TREE_THIS_VOLATILE (expr)) > > > + { > > > + warning_at (location_of (expr), OPT_Wvolatile, > > > + "assignment with %<volatile%>-qualified left " > > > + "operand is deprecated"); > > > > This should be more specific; the assignment itself isn't deprecated, but > > rather using the assignment as an lvalue or rvalue. > > This now reads "using value of simple assignment with volatile-qualified left > operand is deprecated". > > > > + /* An expression of the form E1 op= E2. [expr.ass] says: > > > + "Such expressions are deprecated if E1 has volatile-qualified > > > + type." We warn here rather than in cp_genericize_r because > > > + for compound assignments we are supposed to warn even if the > > > + assignment is a discarded-value expression. */ > > > + if (TREE_THIS_VOLATILE (lhs) || CP_TYPE_VOLATILE_P (lhstype)) > > > + warning_at (loc, OPT_Wvolatile, > > > + "assignment with %<volatile%>-qualified left operand " > > > + "is deprecated"); > > > > And this should say "compound assignment ..." > > Fixed. > > > > +@item -Wvolatile @r{(C++ and Objective-C++ only)} > > > +@opindex Wvolatile > > > +@opindex Wno-volatile > > > +Warn about certain uses of volatile qualifier. This includes postfix > > > +@code{++} and @code{--} expressions, prefix @code{++} and @code{--} > > > +expressions, certain assignments where the left operand is a > > > +volatile-qualified non-class type > > > > This should also be more specific. > > Improved (hopefully). > > > > + > > > + // Unevaluated operand. > > > + decltype(vi = 42) x = vi; > > > > I guess we should also test that there's no warning for > > > > decltype(i = vi = 42) > > > > since this is also an unevaluated context. It's a bit odd the proposal uses > > "unevaluated context" rather than "unevaluated operand". > > Yes we should, and *of course* it was a case where my patch emitted a bogus > warning. But it was trivial to fix by checking cp_unevaluated_operand. > > Bootstrapped/regtested on x86_64-linux, ok for trunk? > > 2019-08-28 Marek Polacek <pola...@redhat.com> > > Implement P1152R4: Deprecating some uses of volatile. > PR c++/91361 > * c-opts.c (c_common_post_options): Enable -Wvolatile by > default for C++2a, unless -Wno-deprecated. > * c.opt (Wvolatile): New warning. > > * cp-gimplify.c (cp_fold): Set TREE_THIS_VOLATILE. > * decl.c (grokdeclarator): Warn about a volatile-qualified structured > binding and return type. > (grokparms): Warn about a volatile-qualified function parameter. > * expr.c (mark_use) <case MODIFY_EXPR>: Emit a -Wvolatile warning. > * typeck.c (cp_build_unary_op): Emit a -Wvolatile warning for pre and > post ++/-- on a volatile operand. > (genericize_compound_lvalue): Use a better location. Don't lose > TREE_THIS_VOLATILE. > (cp_build_modify_expr): Emit a -Wvolatile warning for a compound > assignment whose LHS is volatile-qualified. Build the assignment with > a more precise location. > > * doc/invoke.texi: Document -Wvolatile. > > * c-c++-common/Wbool-operation-1.c: Use -Wno-volatile in C++. > * c-c++-common/gomp/atomic-1.c: Likewise. > * c-c++-common/gomp/atomic-9.c: Likewise. > * c-c++-common/gomp/depend-iterator-1.c: Likewise. > * c-c++-common/gomp/loop-1.c: Adjust warning location for C++. > * c-c++-common/gomp/order-3.c: Likewise. > * c-c++-common/pr69733.c: Use -Wno-volatile in C++. > * c-c++-common/spec-barrier-2.c: Likewise. > * c-c++-common/tm/pr54893.c: Likewise. > * g++.dg/cpp0x/pr65327.C: Add dg-warning. > * g++.dg/cpp0x/rv-conv2.C: Likewise. > * g++.dg/cpp0x/rv1n.C: Likewise. > * g++.dg/cpp0x/rv1p.C: Likewise. > * g++.dg/cpp0x/rv2n.C: Likewise. > * g++.dg/cpp0x/rv2p.C: Likewise. > * g++.dg/cpp0x/rv3n.C: Likewise. > * g++.dg/cpp0x/rv3p.C: Likewise. > * g++.dg/cpp0x/rv4n.C: Likewise. > * g++.dg/cpp0x/rv4p.C: Likewise. > * g++.dg/cpp0x/rv5n.C: Likewise. > * g++.dg/cpp0x/rv5p.C: Likewise. > * g++.dg/cpp0x/rv6n.C: Likewise. > * g++.dg/cpp0x/rv6p.C: Likewise. > * g++.dg/cpp0x/rv7n.C: Likewise. > * g++.dg/cpp0x/rv7p.C: Likewise. > * g++.dg/cpp0x/rv8p.C: Likewise. > * g++.dg/cpp0x/trailing14.C: Use -Wno-volatile. > * g++.dg/cpp1y/new1.C: Add dg-warning. > * g++.dg/cpp2a/volatile1.C: New test. > * g++.dg/cpp2a/volatile2.C: New test. > * g++.dg/cpp2a/volatile3.C: New test. > * g++.dg/cpp2a/volatile4.C: New test. > * g++.dg/expr/bool3.C: Add dg-warning. > * g++.dg/expr/bool4.C: Likewise. > * g++.dg/expr/cond9.C: Likewise. > * g++.dg/ext/vector25.C: Likewise. > * g++.dg/gomp/depend-iterator-1.C: Use -Wno-volatile. > * g++.dg/inherit/covariant21.C: Add dg-warning. > * g++.dg/init/ref18.C: Likewise. > * g++.dg/ipa/pr63838.C: Likewise. > * g++.dg/overload/rvalue2.C: Likewise. > * g++.dg/parse/semicolon4.C: Likewise. > * g++.dg/warn/Wreturn-type-4.C: Likewise. > * g++.dg/warn/pr36069.C: Likewise. > * g++.old-deja/g++.mike/p9506.C: Likewise. > * g++.old-deja/g++.other/volatile1.C: Likewise. > > diff --git gcc/c-family/c-opts.c gcc/c-family/c-opts.c > index da783e4990c..fa8cd0ccb09 100644 > --- gcc/c-family/c-opts.c > +++ gcc/c-family/c-opts.c > @@ -919,6 +919,10 @@ c_common_post_options (const char **pfilename) > if (!global_options_set.x_warn_comma_subscript) > warn_comma_subscript = (cxx_dialect >= cxx2a && warn_deprecated); > > + /* -Wvolatile is enabled by default in C++20. */ > + if (!global_options_set.x_warn_volatile) > + warn_volatile = (cxx_dialect >= cxx2a && warn_deprecated); > + > /* Declone C++ 'structors if -Os. */ > if (flag_declone_ctor_dtor == -1) > flag_declone_ctor_dtor = optimize_size; > diff --git gcc/c-family/c.opt gcc/c-family/c.opt > index 4c468d0f6c2..f8a1a1dbdad 100644 > --- gcc/c-family/c.opt > +++ gcc/c-family/c.opt > @@ -1228,6 +1228,10 @@ Wno-vla-larger-than > C ObjC C++ LTO ObjC++ Alias(Wvla-larger-than=,18446744073709551615EiB,none) > Warning > -Wno-vla-larger-than Disable Wvla-larger-than= warning. Equivalent to > Wvla-larger-than=<SIZE_MAX> or larger. > > +Wvolatile > +C++ ObjC++ Var(warn_volatile) Warning > +Warn about deprecated uses of volatile qualifier. > + > Wvolatile-register-var > C ObjC C++ ObjC++ Var(warn_volatile_register_var) Warning LangEnabledBy(C > ObjC C++ ObjC++,Wall) > Warn when a register variable is declared volatile. > diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c > index 065dcb7ba06..49fa47ac3af 100644 > --- gcc/cp/cp-gimplify.c > +++ gcc/cp/cp-gimplify.c > @@ -2507,6 +2507,9 @@ cp_fold (tree x) > else > x = org_x; > } > + if (code == MODIFY_EXPR && TREE_CODE (x) == MODIFY_EXPR) > + TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x); > + > break; > > case VEC_COND_EXPR: > diff --git gcc/cp/decl.c gcc/cp/decl.c > index c5cc22a8d6d..2aef330455f 100644 > --- gcc/cp/decl.c > +++ gcc/cp/decl.c > @@ -11233,6 +11233,10 @@ grokdeclarator (const cp_declarator *declarator, > if (concept_p) > error_at (declspecs->locations[ds_concept], > "structured binding declaration cannot be %qs", "concept"); > + /* [dcl.struct.bind] "A cv that includes volatile is deprecated." */ > + if (type_quals & TYPE_QUAL_VOLATILE) > + warning_at (declspecs->locations[ds_volatile], OPT_Wvolatile, > + "%<volatile%>-qualified structured binding is > deprecated"); > switch (storage_class) > { > case sc_none: > @@ -11623,6 +11627,13 @@ grokdeclarator (const cp_declarator *declarator, > if (SCALAR_TYPE_P (type) || VOID_TYPE_P (type)) > warning_at (typespec_loc, OPT_Wignored_qualifiers, "type " > "qualifiers ignored on function return type"); > + /* [dcl.fct] "A volatile-qualified return type is > + deprecated." */ > + if (type_quals & TYPE_QUAL_VOLATILE) > + warning_at (typespec_loc, OPT_Wvolatile, > + "%<volatile%>-qualified return type is " > + "deprecated"); > + > /* We now know that the TYPE_QUALS don't apply to the > decl, but to its return type. */ > type_quals = TYPE_UNQUALIFIED; > @@ -13378,6 +13389,13 @@ grokparms (tree parmlist, tree *parms) > cp_warn_deprecated_use (deptype); > } > > + /* [dcl.fct] "A parameter with volatile-qualified type is > + deprecated." */ > + if (CP_TYPE_VOLATILE_P (type)) > + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wvolatile, > + "%<volatile%>-qualified parameter is " > + "deprecated"); > + > /* Top-level qualifiers on the parameters are > ignored for function types. */ > type = cp_build_qualified_type (type, 0); > diff --git gcc/cp/expr.c gcc/cp/expr.c > index 9160043ed11..212a7f93c5a 100644 > --- gcc/cp/expr.c > +++ gcc/cp/expr.c > @@ -207,6 +207,28 @@ mark_use (tree expr, bool rvalue_p, bool read_p, > recurse_op[0] = true; > break; > > + case MODIFY_EXPR: > + { > + tree lhs = TREE_OPERAND (expr, 0); > + /* [expr.ass] "A simple assignment whose left operand is of > + a volatile-qualified type is deprecated unless the assignment > + is either a discarded-value expression or appears in an > + unevaluated context." */ > + if (read_p > + && !cp_unevaluated_operand > + && (TREE_THIS_VOLATILE (lhs) > + || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs))) > + && !TREE_THIS_VOLATILE (expr)) > + { > + warning_at (location_of (expr), OPT_Wvolatile, > + "using value of simple assignment with > %<volatile%>-" > + "qualified left operand is deprecated"); > + /* Make sure not to warn about this assignment again. */ > + TREE_THIS_VOLATILE (expr) = true; > + } > + break; > + } > + > default: > break; > } > diff --git gcc/cp/typeck.c gcc/cp/typeck.c > index c09bb309142..d4f2d98143b 100644 > --- gcc/cp/typeck.c > +++ gcc/cp/typeck.c > @@ -6459,6 +6459,17 @@ cp_build_unary_op (enum tree_code code, tree xarg, > bool noconvert, > complain)) > return error_mark_node; > > + /* [depr.volatile.type] "Postfix ++ and -- expressions and > + prefix ++ and -- expressions of volatile-qualified arithmetic > + and pointer types are deprecated." */ > + if (TREE_THIS_VOLATILE (arg) || CP_TYPE_VOLATILE_P (TREE_TYPE (arg))) > + warning_at (location, OPT_Wvolatile, > + "%qs expression of %<volatile%>-qualified type is " > + "deprecated", > + ((code == PREINCREMENT_EXPR > + || code == POSTINCREMENT_EXPR) > + ? "++" : "--")); > + > /* Forbid using -- or ++ in C++17 on `bool'. */ > if (TREE_CODE (declared_type) == BOOLEAN_TYPE) > { > @@ -8278,6 +8289,15 @@ cp_build_modify_expr (location_t loc, tree lhs, enum > tree_code modifycode, > && MAYBE_CLASS_TYPE_P (TREE_TYPE (lhstype))) > || MAYBE_CLASS_TYPE_P (lhstype))); > > + /* An expression of the form E1 op= E2. [expr.ass] says: > + "Such expressions are deprecated if E1 has volatile-qualified > + type." We warn here rather than in cp_genericize_r because > + for compound assignments we are supposed to warn even if the > + assignment is a discarded-value expression. */ > + if (TREE_THIS_VOLATILE (lhs) || CP_TYPE_VOLATILE_P (lhstype)) > + warning_at (loc, OPT_Wvolatile, > + "compound assignment with %<volatile%>-qualified left > " > + "operand is deprecated"); > /* Preevaluate the RHS to make sure its evaluation is complete > before the lvalue-to-rvalue conversion of the LHS: > > @@ -8450,8 +8470,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum > tree_code modifycode, > goto ret; > } > > - result = build2 (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, > - lhstype, lhs, newrhs); > + result = build2_loc (loc, modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, > + lhstype, lhs, newrhs); > > TREE_SIDE_EFFECTS (result) = 1; > if (!plain_assign) > diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi > index 1391a562c35..aa9886ee09f 100644 > --- gcc/doc/invoke.texi > +++ gcc/doc/invoke.texi > @@ -243,7 +243,7 @@ in the following sections. > -Wno-non-template-friend -Wold-style-cast @gol > -Woverloaded-virtual -Wno-pmf-conversions @gol > -Wno-class-conversion -Wno-terminate @gol > --Wsign-promo -Wvirtual-inheritance} > +-Wsign-promo -Wvirtual-inheritance -Wvolatile} > > @item Objective-C and Objective-C++ Language Options > @xref{Objective-C and Objective-C++ Dialect Options,,Options Controlling > @@ -3516,6 +3516,19 @@ result in a call to @code{terminate}. > Disable the warning about the case when a conversion function converts an > object to the same type, to a base class of that type, or to void; such > a conversion function will never be called. > + > +@item -Wvolatile @r{(C++ and Objective-C++ only)} > +@opindex Wvolatile > +@opindex Wno-volatile > +Warn about deprecated uses of the volatile qualifier. This includes postfix > +and prefix @code{++} and @code{--} expressions of volatile-qualified types, > +using simple assignments where the left operand is a volatile-qualified > +non-class type for their value, compound assignments where the left operand > +is a volatile-qualified non-class type, volatile-qualified function return > +type, volatile-qualified parameter type, and structured bindings of a > +volatile-qualified type. This usage was deprecated in C++20. > + > +Enabled by default with @option{-std=c++2a}. > @end table > > @node Objective-C and Objective-C++ Dialect Options > diff --git gcc/testsuite/c-c++-common/Wbool-operation-1.c > gcc/testsuite/c-c++-common/Wbool-operation-1.c > index 04891878155..ce87705692a 100644 > --- gcc/testsuite/c-c++-common/Wbool-operation-1.c > +++ gcc/testsuite/c-c++-common/Wbool-operation-1.c > @@ -1,6 +1,7 @@ > /* PR c/77490 */ > /* { dg-do compile } */ > /* { dg-options "-Wall -Wno-psabi" } */ > +/* { dg-additional-options "-Wno-volatile" { target c++ } } */ > > #ifndef __cplusplus > # define bool _Bool > diff --git gcc/testsuite/c-c++-common/gomp/atomic-1.c > gcc/testsuite/c-c++-common/gomp/atomic-1.c > index 3e4bc569ba7..1facf4586f5 100644 > --- gcc/testsuite/c-c++-common/gomp/atomic-1.c > +++ gcc/testsuite/c-c++-common/gomp/atomic-1.c > @@ -1,4 +1,5 @@ > /* { dg-do compile } */ > +/* { dg-additional-options "-Wno-volatile" { target c++ } } */ > > int x; > volatile int y; > diff --git gcc/testsuite/c-c++-common/gomp/atomic-9.c > gcc/testsuite/c-c++-common/gomp/atomic-9.c > index c07da8fc712..35548395f36 100644 > --- gcc/testsuite/c-c++-common/gomp/atomic-9.c > +++ gcc/testsuite/c-c++-common/gomp/atomic-9.c > @@ -1,5 +1,6 @@ > /* { dg-do compile } */ > /* { dg-options "-fopenmp -fdump-tree-ompexp" } */ > +/* { dg-additional-options "-Wno-volatile" { target c++ } } */ > /* { dg-require-effective-target cas_int } */ > > volatile int *bar(void); > diff --git gcc/testsuite/c-c++-common/gomp/depend-iterator-1.c > gcc/testsuite/c-c++-common/gomp/depend-iterator-1.c > index 4fb01c174ec..6fa60215f43 100644 > --- gcc/testsuite/c-c++-common/gomp/depend-iterator-1.c > +++ gcc/testsuite/c-c++-common/gomp/depend-iterator-1.c > @@ -1,3 +1,5 @@ > +/* { dg-additional-options "-Wno-volatile" { target c++ } } */ > + > int arr[64], arr2[64]; > struct S { int a[4]; } k; > short arr4[4]; > diff --git gcc/testsuite/c-c++-common/gomp/loop-1.c > gcc/testsuite/c-c++-common/gomp/loop-1.c > index d2f943aea54..4fb995c02a7 100644 > --- gcc/testsuite/c-c++-common/gomp/loop-1.c > +++ gcc/testsuite/c-c++-common/gomp/loop-1.c > @@ -100,8 +100,8 @@ f4 (int *a) > #pragma omp loop order(concurrent) bind(parallel) > for (i = 0; i < 64; i++) > { > - #pragma omp atomic read > - a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > 'loop' region" } */ > + #pragma omp atomic read /* { dg-error "OpenMP constructs > other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' > region" "" { target c++ } } */ > + a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > 'loop' region" "" { target c } } */ > } > #pragma omp loop order(concurrent) bind(parallel) > for (i = 0; i < 64; i++) > @@ -172,8 +172,8 @@ f5 (int *a) > #pragma omp loop > for (i = 0; i < 64; i++) > { > - #pragma omp atomic read > - a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > 'loop' region" } */ > + #pragma omp atomic read /* { dg-error "OpenMP constructs > other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' > region" "" { target c++ } } */ > + a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > 'loop' region" "" { target c } } */ > } > #pragma omp loop > for (i = 0; i < 64; i++) > @@ -245,8 +245,8 @@ f6 (int *a) > #pragma omp loop > for (i = 0; i < 64; i++) > { > - #pragma omp atomic read > - a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > 'loop' region" } */ > + #pragma omp atomic read /* { dg-error "OpenMP constructs > other than 'parallel', 'loop' or 'simd' may not be nested inside a 'loop' > region" "" { target c++ } } */ > + a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > 'loop' region" "" { target c } } */ > } > #pragma omp loop > for (i = 0; i < 64; i++) > diff --git gcc/testsuite/c-c++-common/gomp/order-3.c > gcc/testsuite/c-c++-common/gomp/order-3.c > index 2d51bf37749..e33386dd5cc 100644 > --- gcc/testsuite/c-c++-common/gomp/order-3.c > +++ gcc/testsuite/c-c++-common/gomp/order-3.c > @@ -50,8 +50,8 @@ f1 (int *a) > #pragma omp simd order(concurrent) > for (i = 0; i < 64; i++) > { > - #pragma omp atomic read > - a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > region with the 'order\\(concurrent\\)' clause" } */ > + #pragma omp atomic read /* { dg-error "OpenMP constructs > other than 'parallel', 'loop' or 'simd' may not be nested inside a region > with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ > + a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > region with the 'order\\(concurrent\\)' clause" "" { target c } } */ > } > #pragma omp simd order(concurrent) > for (i = 0; i < 64; i++) > @@ -112,8 +112,8 @@ f2 (int *a) > #pragma omp for simd order(concurrent) > for (i = 0; i < 64; i++) > { > - #pragma omp atomic read > - a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > region with the 'order\\(concurrent\\)' clause" } */ > + #pragma omp atomic read /* { dg-error "OpenMP constructs > other than 'parallel', 'loop' or 'simd' may not be nested inside a region > with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ > + a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > region with the 'order\\(concurrent\\)' clause" "" { target c } } */ > } > #pragma omp for simd order(concurrent) > for (i = 0; i < 64; i++) > @@ -174,8 +174,8 @@ f3 (int *a) > #pragma omp for order(concurrent) > for (i = 0; i < 64; i++) > { > - #pragma omp atomic read > - a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > region with the 'order\\(concurrent\\)' clause" } */ > + #pragma omp atomic read /* { dg-error "OpenMP constructs > other than 'parallel', 'loop' or 'simd' may not be nested inside a region > with the 'order\\(concurrent\\)' clause" "" { target c++ } } */ > + a[i] = v; /* { dg-error "OpenMP > constructs other than 'parallel', 'loop' or 'simd' may not be nested inside a > region with the 'order\\(concurrent\\)' clause" "" { target c } } */ > } > #pragma omp for order(concurrent) > for (i = 0; i < 64; i++) > diff --git gcc/testsuite/c-c++-common/pr69733.c > gcc/testsuite/c-c++-common/pr69733.c > index 57ec1eccb9f..ab70f49009c 100644 > --- gcc/testsuite/c-c++-common/pr69733.c > +++ gcc/testsuite/c-c++-common/pr69733.c > @@ -1,5 +1,6 @@ > /* { dg-do compile } */ > /* { dg-options "-W -fdiagnostics-show-caret" } */ > +/* { dg-additional-options "-Wno-volatile" { target c++ } } */ > > typedef const double cd; > double val; > @@ -21,4 +22,3 @@ cd val2() {return val;} /* { dg-warning "qualifiers > ignored" } */ > cd val2() {return val;} > ^~ > { dg-end-multiline-output "" } */ > - > diff --git gcc/testsuite/c-c++-common/spec-barrier-2.c > gcc/testsuite/c-c++-common/spec-barrier-2.c > index b09567e62a9..a27ec54f0d3 100644 > --- gcc/testsuite/c-c++-common/spec-barrier-2.c > +++ gcc/testsuite/c-c++-common/spec-barrier-2.c > @@ -1,4 +1,5 @@ > /* { dg-do run } */ > +/* { dg-additional-options "-Wno-volatile" { target c++ } } */ > > /* Even on targets that don't need the optional failval parameter, > side-effects on the operand should still be calculated. */ > diff --git gcc/testsuite/c-c++-common/tm/pr54893.c > gcc/testsuite/c-c++-common/tm/pr54893.c > index 3766078d31e..266cbe9c652 100644 > --- gcc/testsuite/c-c++-common/tm/pr54893.c > +++ gcc/testsuite/c-c++-common/tm/pr54893.c > @@ -1,5 +1,6 @@ > /* { dg-do compile } */ > /* { dg-options "-fgnu-tm -fdump-ipa-tmipa" } */ > +/* { dg-additional-options "-Wno-volatile" { target c++ } } */ > > /* Test that volatiles are allowed inside relaxed transactions. */ > > diff --git gcc/testsuite/g++.dg/cpp0x/pr65327.C > gcc/testsuite/g++.dg/cpp0x/pr65327.C > index 5176b3c3204..6e888ebff2c 100644 > --- gcc/testsuite/g++.dg/cpp0x/pr65327.C > +++ gcc/testsuite/g++.dg/cpp0x/pr65327.C > @@ -11,7 +11,7 @@ foo () > static constexpr volatile int k = 5; > } > > -constexpr volatile int > +constexpr volatile int // { dg-warning "deprecated" "" { target c++2a } } > bar () > { > return i; > diff --git gcc/testsuite/g++.dg/cpp0x/rv-conv2.C > gcc/testsuite/g++.dg/cpp0x/rv-conv2.C > index 9b9b154995b..2f2a1fa702a 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv-conv2.C > +++ gcc/testsuite/g++.dg/cpp0x/rv-conv2.C > @@ -1,16 +1,16 @@ > // PR c++/89705 > // { dg-do compile { target c++11 } } > > -struct W { operator const volatile int(); }; > +struct W { operator const volatile int(); }; // { dg-warning "deprecated" "" > { target c++2a } } > const int& rci = W(); > > struct X { operator const int(); }; > int&& rri = X(); > > -struct Y { operator volatile int(); }; > +struct Y { operator volatile int(); }; // { dg-warning "deprecated" "" { > target c++2a } } > int&& rri2 = Y(); > > -struct Z { operator const volatile int(); }; > +struct Z { operator const volatile int(); }; // { dg-warning "deprecated" "" > { target c++2a } } > volatile int&& rri3 = Z(); > > enum E { A }; > diff --git gcc/testsuite/g++.dg/cpp0x/rv1n.C gcc/testsuite/g++.dg/cpp0x/rv1n.C > index f5e75681758..a762fc85862 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv1n.C > +++ gcc/testsuite/g++.dg/cpp0x/rv1n.C > @@ -26,8 +26,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 1 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv1p.C gcc/testsuite/g++.dg/cpp0x/rv1p.C > index a9097276d5a..e2a983a7708 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv1p.C > +++ gcc/testsuite/g++.dg/cpp0x/rv1p.C > @@ -26,8 +26,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 1 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv2n.C gcc/testsuite/g++.dg/cpp0x/rv2n.C > index 65eda80fba0..2871ccf9ab3 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv2n.C > +++ gcc/testsuite/g++.dg/cpp0x/rv2n.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 2 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv2p.C gcc/testsuite/g++.dg/cpp0x/rv2p.C > index 25a42ba2af8..bab0dce3d97 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv2p.C > +++ gcc/testsuite/g++.dg/cpp0x/rv2p.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 2 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv3n.C gcc/testsuite/g++.dg/cpp0x/rv3n.C > index 4549438f8ef..35cdba95858 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv3n.C > +++ gcc/testsuite/g++.dg/cpp0x/rv3n.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 3 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv3p.C gcc/testsuite/g++.dg/cpp0x/rv3p.C > index 2d7d78df6be..b25aa26c9b0 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv3p.C > +++ gcc/testsuite/g++.dg/cpp0x/rv3p.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 3 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv4n.C gcc/testsuite/g++.dg/cpp0x/rv4n.C > index 29deb3fc81b..6941a13de6c 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv4n.C > +++ gcc/testsuite/g++.dg/cpp0x/rv4n.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 4 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv4p.C gcc/testsuite/g++.dg/cpp0x/rv4p.C > index 0e4903bc291..cd0d631d780 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv4p.C > +++ gcc/testsuite/g++.dg/cpp0x/rv4p.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 4 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv5n.C gcc/testsuite/g++.dg/cpp0x/rv5n.C > index f11d07a3921..086aa460c68 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv5n.C > +++ gcc/testsuite/g++.dg/cpp0x/rv5n.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 5 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv5p.C gcc/testsuite/g++.dg/cpp0x/rv5p.C > index 63441a3f0da..34c1017f578 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv5p.C > +++ gcc/testsuite/g++.dg/cpp0x/rv5p.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 5 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv6n.C gcc/testsuite/g++.dg/cpp0x/rv6n.C > index 0ebbe33e1d1..b21d22a5b87 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv6n.C > +++ gcc/testsuite/g++.dg/cpp0x/rv6n.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 6 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv6p.C gcc/testsuite/g++.dg/cpp0x/rv6p.C > index 26714f0c9aa..fee692bb08f 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv6p.C > +++ gcc/testsuite/g++.dg/cpp0x/rv6p.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 6 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv7n.C gcc/testsuite/g++.dg/cpp0x/rv7n.C > index d9e371b8adb..5bc313cc07f 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv7n.C > +++ gcc/testsuite/g++.dg/cpp0x/rv7n.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 7 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv7p.C gcc/testsuite/g++.dg/cpp0x/rv7p.C > index 60a35835c7d..b0b8f965498 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv7p.C > +++ gcc/testsuite/g++.dg/cpp0x/rv7p.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 7 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/rv8p.C gcc/testsuite/g++.dg/cpp0x/rv8p.C > index e12da4b8d79..287fb93b432 100644 > --- gcc/testsuite/g++.dg/cpp0x/rv8p.C > +++ gcc/testsuite/g++.dg/cpp0x/rv8p.C > @@ -25,8 +25,8 @@ struct A > > A source(); > const A c_source(); > - volatile A v_source(); > -const volatile A cv_source(); > + volatile A v_source(); // { dg-warning "deprecated" "" { target c++2a > } } > +const volatile A cv_source(); // { dg-warning "deprecated" "" { target c++2a > } } > > // 8 at a time > > diff --git gcc/testsuite/g++.dg/cpp0x/trailing14.C > gcc/testsuite/g++.dg/cpp0x/trailing14.C > index 2544d0bab5e..4ebb37406ad 100644 > --- gcc/testsuite/g++.dg/cpp0x/trailing14.C > +++ gcc/testsuite/g++.dg/cpp0x/trailing14.C > @@ -1,6 +1,6 @@ > // PR c++/65775 > // { dg-do compile { target c++11 } } > -// { dg-options "-Wignored-qualifiers" } > +// { dg-options "-Wignored-qualifiers -Wno-volatile" } > > using Qi = int const volatile; > Qi q1(); // { dg-warning "1: type qualifiers ignored" } > diff --git gcc/testsuite/g++.dg/cpp1y/new1.C gcc/testsuite/g++.dg/cpp1y/new1.C > index 5e4f1bf6b0b..b9ad64dfcc0 100644 > --- gcc/testsuite/g++.dg/cpp1y/new1.C > +++ gcc/testsuite/g++.dg/cpp1y/new1.C > @@ -65,7 +65,7 @@ void > test_unused() { > volatile double d = 0.0; > double *p = new double (); > - d += 1.0; > + d += 1.0; // { dg-warning "deprecated" "" { target c++2a } } > delete p; > } > > diff --git gcc/testsuite/g++.dg/cpp2a/volatile1.C > gcc/testsuite/g++.dg/cpp2a/volatile1.C > new file mode 100644 > index 00000000000..e47591b13bc > --- /dev/null > +++ gcc/testsuite/g++.dg/cpp2a/volatile1.C > @@ -0,0 +1,141 @@ > +// PR c++/91361 - P1152R4: Deprecating some uses of volatile. > +// { dg-do compile { target c++17 } } > + > +#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 // { dg-warning ".volatile.-qualified return type is > deprecated" "" { target c++2a } } > +fn (volatile int i) // { dg-warning ".volatile.-qualified parameter is > deprecated" "" { target c++2a } } > +{ > + volatile int v = 10; > + int *volatile p = nullptr; > + > + // Pre/post ++/--. > + v++; // { dg-warning "expression of .volatile.-qualified type is > deprecated" "" { target c++2a } } > + ++v; // { dg-warning "expression of .volatile.-qualified type is > deprecated" "" { target c++2a } } > + v--; // { dg-warning "expression of .volatile.-qualified type is > deprecated" "" { target c++2a } } > + --v; // { dg-warning "expression of .volatile.-qualified type is > deprecated" "" { target c++2a } } > + p++; // { dg-warning "expression of .volatile.-qualified type is > deprecated" "" { target c++2a } } > + ++p; // { dg-warning "expression of .volatile.-qualified type is > deprecated" "" { target c++2a } } > + p--; // { dg-warning "expression of .volatile.-qualified type is > deprecated" "" { target c++2a } } > + --p; // { dg-warning "expression of .volatile.-qualified type is > deprecated" "" { target c++2a } } > + 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; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + &(vi = i); // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + (vi = 42, 45); > + (i = vi = 42, 10); // { dg-warning "assignment with .volatile.-qualified > left operand is deprecated" "" { target c++2a } } > + i = vi; // LHS not volatile. > + i = (vi = i, 42); > + static_cast<void>(vi = i); > + static_cast<void>(i = vi = 42); // { dg-warning "assignment with > .volatile.-qualified left operand is deprecated" "" { target c++2a } } > + (void)(vi = i); > + (void)(i = vi = 42); // { dg-warning "assignment with .volatile.-qualified > left operand is deprecated" "" { target c++2a } } > + > + // Unevaluated operand. > + decltype(vi = 42) x = vi; > + decltype(i = vi = 42) x3 = i; > + > + // Compound assignments. > + vi += i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + vi -= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + vi %= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + vi ^= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + vi |= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + vi /= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + vi = vi += 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + vi += vi = 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + i *= vi; > + decltype(vi -= 42) x2 = vi; // { dg-warning "assignment with > .volatile.-qualified left operand is deprecated" "" { target c++2a } } > + > + // Structured bindings. > + int a[] = { 10, 5 }; > + const auto & [cxr, cyr] = a; > + const volatile auto & [cvxr, cvyr] = a; // { dg-warning > ".volatile.-qualified structured binding is deprecated" "" { target c++2a } } > + volatile auto & [vxr, vyr] = a; // { dg-warning ".volatile.-qualified > structured binding is deprecated" "" { target c++2a } } > +} > + > +void > +fn3 () > +{ > + volatile int i, j, k = 0; > + i = j = k; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + > + ACCESS_ONCE(j); > + > + S s; > + s.b = 1; > + > + volatile U u; > + u.c = 42; > + i = u.c = 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + u.c += 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + > + volatile T t; > + t.a = 3; > + j = t.a = 3; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + t.a += 3; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + > + 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; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > + t &= 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" "" { target c++2a } } > +} > + > +void > +fn5 () > +{ > + raccoon<int>(); > +} > diff --git gcc/testsuite/g++.dg/cpp2a/volatile2.C > gcc/testsuite/g++.dg/cpp2a/volatile2.C > new file mode 100644 > index 00000000000..1a7889a6a8c > --- /dev/null > +++ gcc/testsuite/g++.dg/cpp2a/volatile2.C > @@ -0,0 +1,142 @@ > +// PR c++/91361 - P1152R4: Deprecating some uses of volatile. > +// { dg-do compile { target c++2a } } > +// { 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>(); > +} > diff --git gcc/testsuite/g++.dg/cpp2a/volatile3.C > gcc/testsuite/g++.dg/cpp2a/volatile3.C > new file mode 100644 > index 00000000000..f10a29756a9 > --- /dev/null > +++ gcc/testsuite/g++.dg/cpp2a/volatile3.C > @@ -0,0 +1,142 @@ > +// PR c++/91361 - P1152R4: Deprecating some uses of volatile. > +// { dg-do compile { target c++17 } } > +// { dg-options "-Wvolatile" } > + > +#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 // { dg-warning ".volatile.-qualified return type is > deprecated" } > +fn (volatile int i) // { dg-warning ".volatile.-qualified parameter is > deprecated" } > +{ > + volatile int v = 10; > + int *volatile p = nullptr; > + > + // Pre/post ++/--. > + v++; // { dg-warning "expression of .volatile.-qualified type is > deprecated" } > + ++v; // { dg-warning "expression of .volatile.-qualified type is > deprecated" } > + v--; // { dg-warning "expression of .volatile.-qualified type is > deprecated" } > + --v; // { dg-warning "expression of .volatile.-qualified type is > deprecated" } > + p++; // { dg-warning "expression of .volatile.-qualified type is > deprecated" } > + ++p; // { dg-warning "expression of .volatile.-qualified type is > deprecated" } > + p--; // { dg-warning "expression of .volatile.-qualified type is > deprecated" } > + --p; // { dg-warning "expression of .volatile.-qualified type is > deprecated" } > + 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; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + &(vi = i); // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + (vi = 42, 45); > + (i = vi = 42, 10); // { dg-warning "assignment with .volatile.-qualified > left operand is deprecated" } > + i = vi; // LHS not volatile. > + i = (vi = i, 42); > + static_cast<void>(vi = i); > + static_cast<void>(i = vi = 42); // { dg-warning "assignment with > .volatile.-qualified left operand is deprecated" } > + (void)(vi = i); > + (void)(i = vi = 42); // { dg-warning "assignment with .volatile.-qualified > left operand is deprecated" } > + > + // Unevaluated operand. > + decltype(vi = 42) x = vi; > + decltype(i = vi = 42) x3 = i; > + > + // Compound assignments. > + vi += i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + vi -= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + vi %= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + vi ^= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + vi |= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + vi /= i; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + vi = vi += 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + vi += vi = 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + i *= vi; > + decltype(vi -= 42) x2 = vi; // { dg-warning "assignment with > .volatile.-qualified left operand is deprecated" } > + > + // Structured bindings. > + int a[] = { 10, 5 }; > + const auto & [cxr, cyr] = a; > + const volatile auto & [cvxr, cvyr] = a; // { dg-warning > ".volatile.-qualified structured binding is deprecated" } > + volatile auto & [vxr, vyr] = a; // { dg-warning ".volatile.-qualified > structured binding is deprecated" } > +} > + > +void > +fn3 () > +{ > + volatile int i, j, k = 0; > + i = j = k; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + > + ACCESS_ONCE(j); > + > + S s; > + s.b = 1; > + > + volatile U u; > + u.c = 42; > + i = u.c = 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + u.c += 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + > + volatile T t; > + t.a = 3; > + j = t.a = 3; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + t.a += 3; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + > + 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; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > + t &= 42; // { dg-warning "assignment with .volatile.-qualified left > operand is deprecated" } > +} > + > +void > +fn5 () > +{ > + raccoon<int>(); > +} > diff --git gcc/testsuite/g++.dg/cpp2a/volatile4.C > gcc/testsuite/g++.dg/cpp2a/volatile4.C > new file mode 100644 > index 00000000000..2148cdeb3d1 > --- /dev/null > +++ gcc/testsuite/g++.dg/cpp2a/volatile4.C > @@ -0,0 +1,142 @@ > +// 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<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>(); > +} > diff --git gcc/testsuite/g++.dg/expr/bool3.C gcc/testsuite/g++.dg/expr/bool3.C > index 373c202b800..f27399cfc8a 100644 > --- gcc/testsuite/g++.dg/expr/bool3.C > +++ gcc/testsuite/g++.dg/expr/bool3.C > @@ -13,8 +13,10 @@ int main() > > b++; // { dg-warning "deprecated" "" { target { ! c++17 } } } > // { dg-error "forbidden" "" { target c++17 } .-1 } > + // { dg-warning ".volatile.-qualified type is deprecated" "" { target > c++2a } .-2 } > b++; // { dg-warning "deprecated" "" { target { ! c++17 } } } > // { dg-error "forbidden" "" { target c++17 } .-1 } > + // { dg-warning ".volatile.-qualified type is deprecated" "" { target > c++2a } .-2 } > i = b; > if (i != 1) > abort (); > diff --git gcc/testsuite/g++.dg/expr/bool4.C gcc/testsuite/g++.dg/expr/bool4.C > index dce51ec332e..5891bc311bd 100644 > --- gcc/testsuite/g++.dg/expr/bool4.C > +++ gcc/testsuite/g++.dg/expr/bool4.C > @@ -8,6 +8,6 @@ int main() > { > my_bool b = false; > b--; // { dg-error "" } > + // { dg-warning ".volatile.-qualified type is deprecated" "" { target > c++2a } .-1 } > return 0; > } > - > diff --git gcc/testsuite/g++.dg/expr/cond9.C gcc/testsuite/g++.dg/expr/cond9.C > index b344c1f683a..f7e092e1445 100644 > --- gcc/testsuite/g++.dg/expr/cond9.C > +++ gcc/testsuite/g++.dg/expr/cond9.C > @@ -4,7 +4,7 @@ struct A { // { dg-message "A" } > A(int); > }; > > -void foo(volatile A a) { > +void foo(volatile A a) { // { dg-warning "deprecated" "" { target c++2a } } > 1 ? a : 0; // { dg-error "qualifiers|lvalue|no match" } > 1 ? 0 : a; // { dg-error "qualifiers|lvalue|no match" } > } > diff --git gcc/testsuite/g++.dg/ext/vector25.C > gcc/testsuite/g++.dg/ext/vector25.C > index 6c1f5d09878..339865d6942 100644 > --- gcc/testsuite/g++.dg/ext/vector25.C > +++ gcc/testsuite/g++.dg/ext/vector25.C > @@ -2,5 +2,5 @@ volatile int i __attribute__((vector_size(8))); > > void foo() > { > - i += i; > + i += i; // { dg-warning "deprecated" "" { target c++2a } } > } > diff --git gcc/testsuite/g++.dg/gomp/depend-iterator-1.C > gcc/testsuite/g++.dg/gomp/depend-iterator-1.C > index 6f4aa97ee44..d12670c5159 100644 > --- gcc/testsuite/g++.dg/gomp/depend-iterator-1.C > +++ gcc/testsuite/g++.dg/gomp/depend-iterator-1.C > @@ -1,3 +1,5 @@ > +// { dg-additional-options "-Wno-volatile" } > + > int arr[64], arr2[64]; > struct S { int a[4]; } k; > short arr4[4]; > diff --git gcc/testsuite/g++.dg/inherit/covariant21.C > gcc/testsuite/g++.dg/inherit/covariant21.C > index 42cdf870081..769cb14ecbc 100644 > --- gcc/testsuite/g++.dg/inherit/covariant21.C > +++ gcc/testsuite/g++.dg/inherit/covariant21.C > @@ -6,12 +6,12 @@ struct C : A, B {}; > > struct X > { > - virtual B* foo(volatile int); > + virtual B* foo(volatile int); // { dg-warning "deprecated" "" { target > c++2a } } > }; > > struct Y : X > { > - virtual C* foo(volatile int); > + virtual C* foo(volatile int); // { dg-warning "deprecated" "" { target > c++2a } } > }; > > -C* Y::foo(volatile int) { return 0; } > +C* Y::foo(volatile int) { return 0; } // { dg-warning "deprecated" "" { > target c++2a } } > diff --git gcc/testsuite/g++.dg/init/ref18.C gcc/testsuite/g++.dg/init/ref18.C > index e704077c26b..81ac76a40d3 100644 > --- gcc/testsuite/g++.dg/init/ref18.C > +++ gcc/testsuite/g++.dg/init/ref18.C > @@ -1,6 +1,6 @@ > // PR c++/49395 > > -volatile int foo(); > +volatile int foo(); // { dg-warning "deprecated" "" { target c++2a } } > struct A { volatile int i; }; > typedef volatile int vi; > > diff --git gcc/testsuite/g++.dg/ipa/pr63838.C > gcc/testsuite/g++.dg/ipa/pr63838.C > index d23b3133748..5b6b11d70e5 100644 > --- gcc/testsuite/g++.dg/ipa/pr63838.C > +++ gcc/testsuite/g++.dg/ipa/pr63838.C > @@ -7,12 +7,12 @@ > __attribute__((noinline, noclone)) static void bar (int); > volatile int v; > void (*fn) (); > -struct S { S () { v++; } ~S () { v++; } }; > +struct S { S () { v++; } ~S () { v++; } }; // { dg-warning "deprecated" "" { > target c++2a } } > > __attribute__((noinline, noclone)) static void > foo (int x) > { > - v++; > + v++; // { dg-warning "deprecated" "" { target c++2a } } > if (x == 5) > bar (x); > } > @@ -20,7 +20,7 @@ foo (int x) > __attribute__((noinline, noclone)) static void > bar (int x) > { > - v++; > + v++; // { dg-warning "deprecated" "" { target c++2a } } > if (x == 6) > foo (x); > else if (x == 5) > diff --git gcc/testsuite/g++.dg/overload/rvalue2.C > gcc/testsuite/g++.dg/overload/rvalue2.C > index 8a2290dc293..a829fb5e8cc 100644 > --- gcc/testsuite/g++.dg/overload/rvalue2.C > +++ gcc/testsuite/g++.dg/overload/rvalue2.C > @@ -7,5 +7,5 @@ template <class T> void f(const T&); > int main() > { > volatile int i = 0; > - f(i++); > + f(i++); // { dg-warning "deprecated" "" { target c++2a } } > } > diff --git gcc/testsuite/g++.dg/parse/semicolon4.C > gcc/testsuite/g++.dg/parse/semicolon4.C > index 5135ec14b1f..bdd1c845187 100644 > --- gcc/testsuite/g++.dg/parse/semicolon4.C > +++ gcc/testsuite/g++.dg/parse/semicolon4.C > @@ -25,7 +25,7 @@ struct E1 > } const; // { dg-error "'const' can only be specified > for objects and functions" } > > void foo ( > -struct E2 > +struct E2 // { dg-warning "deprecated" "" { target > c++2a } } > { // { dg-error "types may not be defined in > parameter types" } > int i; > } volatile); > diff --git gcc/testsuite/g++.dg/warn/Wreturn-type-4.C > gcc/testsuite/g++.dg/warn/Wreturn-type-4.C > index 4f02678e7f9..24a6b41cbd8 100644 > --- gcc/testsuite/g++.dg/warn/Wreturn-type-4.C > +++ gcc/testsuite/g++.dg/warn/Wreturn-type-4.C > @@ -3,6 +3,7 @@ > /* { dg-options "-Wignored-qualifiers" } */ > > volatile void bar(); /* { dg-warning "type qualifiers ignored" } */ > +// { dg-warning ".volatile.-qualified return type is deprecated" "" { target > c++2a } .-1 } > > struct A > { > diff --git gcc/testsuite/g++.dg/warn/pr36069.C > gcc/testsuite/g++.dg/warn/pr36069.C > index efb35c25716..7b166351a4b 100644 > --- gcc/testsuite/g++.dg/warn/pr36069.C > +++ gcc/testsuite/g++.dg/warn/pr36069.C > @@ -6,11 +6,13 @@ struct foo { > bool a; > volatile bool b,c; > foo() { a = b = c = false; } // { dg-bogus "parentheses" } > + // { dg-warning "deprecated" "" { target c++2a } .-1 } > }; > > int main() { > bool a; > volatile bool b,c; > a = b = c = false; // { dg-bogus "parentheses" } > + // { dg-warning "deprecated" "" { target c++2a } .-1 } > foo A; > } > diff --git gcc/testsuite/g++.old-deja/g++.mike/p9506.C > gcc/testsuite/g++.old-deja/g++.mike/p9506.C > index db16e3738e2..97594640f96 100644 > --- gcc/testsuite/g++.old-deja/g++.mike/p9506.C > +++ gcc/testsuite/g++.old-deja/g++.mike/p9506.C > @@ -3,5 +3,5 @@ > > char * volatile p; > void foo() { > - --p = 0; > + --p = 0; // { dg-warning "deprecated" "" { target c++2a } } > } > diff --git gcc/testsuite/g++.old-deja/g++.other/volatile1.C > gcc/testsuite/g++.old-deja/g++.other/volatile1.C > index 7d818fbe9e1..a93ef58aa9f 100644 > --- gcc/testsuite/g++.old-deja/g++.other/volatile1.C > +++ gcc/testsuite/g++.old-deja/g++.other/volatile1.C > @@ -5,7 +5,7 @@ > class f_class // { dg-message "note" "candidates" } > { }; > > -volatile f_class > +volatile f_class // { dg-warning "deprecated" "" { target c++2a > } } > ret_v_f_class() > { > f_class t;