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))
     {

Reply via email to