https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84699
Bug ID: 84699 Summary: discarded value expression of volatile class type shall materialize a temporary Product: gcc Version: 7.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: okannen at gmail dot com Target Milestone: --- *Description When a discarded value expression if of class type, a temporary shall be created by copy construction. This copy construction causes the access to the value of the copied object. Example: struct s{ int i; s()=default; s(const volatile s& o):i{o.i}{} }; struct s1{ int i; }; volatile s as; volatile s1 as1; void test(){ as; //should call the copy constructor of s as1; //should not compile (void)as; //should call the copy constructor of s (void)as1; //should not compile (as,as); //should call twice the copy constructor of s (as1,as1); //should not compile } Remark: Neither Clang nor MSVC behave according to the standard. *Standard requirement: **Since at least C++11,[expr].11 (https://timsong-cpp.github.io/cppwp/n4140/expr#11): In some contexts, an expression only appears for its side effects. Such an expression is called a discarded-value expression. The expression is evaluated and its value is discarded. The array-to-pointer ([conv.array]) and function-to-pointer ([conv.func]) standard conversions are not applied. The lvalue-to-rvalue conversion ([conv.lval]) is applied if and only if the expression is a glvalue of volatile-qualified type and it is one of the following:[...] **Since C++14 standard a Note has been added to this which is explicit (https://timsong-cpp.github.io/cppwp/n4659/expr#12): [[...] If the lvalue is of class type, it must have a volatile copy constructor to initialize the temporary that is the result of the lvalue-to-rvalue conversion.]