c++: side effect in nullptr_t conversion fix

Message ID CAPfxnSk8vgLAXGVJb_TZq+yJL1EEZ2B9x6yFnDDkruu5tTUUZA@mail.gmail.com
State Corrupt patch
Headers
Series c++: side effect in nullptr_t conversion fix |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Dmitry Drozodv Jan. 9, 2024, 8:20 a.m. UTC
  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.

---
   else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form))
     {
  

Comments

Jakub Jelinek Jan. 9, 2024, 8:36 a.m. UTC | #1
On Tue, Jan 09, 2024 at 11:20:02AM +0300, Dmitry Drozodv wrote:
> 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))

This looks incorrect.  You can't throw all side-effects away.
Consider expr being say a function call which returns std::nullptr_t,
the function still has to be called, not ignored.

	Jakub
  

Patch

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;
     }