According C++ standard [conv.lval]p3.1: If T is cv std::nullptr_t, the result is a null pointer constant. [Note: Since the conversion does not access the object to which the glvalue refers, there is no side effect even if T is volatile-qualified, and the glvalue can refer to an inactive member of a union. — end note]
The following example demonstrates reading from a volatile std::nullptr_t variable: ```c++ int* foo() { volatile auto a = nullptr; int* b = a; return b; } ``` `g++ -O3 foo.cc` produces: ```asm mov QWORD PTR [rsp-8], 0 # volatile auto a = nullptr; mov rax, QWORD PTR [rsp-8 ] # int* b = a; xor eax, eax ret ``` Here reading from `a` does produce the side effect, which is contrary to the standard. --- diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index cbed847b343..14462356a0e 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -218,8 +218,9 @@ cp_convert_to_pointer (tree type, tree expr, bool dofold, ? build_int_cst_type (type, -1) : build_int_cst (type, 0)); - return (TREE_SIDE_EFFECTS (expr) - ? build2 (COMPOUND_EXPR, type, expr, val) : val); + /* C++ [conv.lval]p3.1: + If T is cv std::nullptr_t, the result is a null pointer constant. */ + return val; } else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form)) {