Hello, You are absolutely right, we can't throw all side-effects away. Example: ```c++ auto __attribute__ ((noinline)) bar() { volatile int* b = (int *)0xff; *b = 10; volatile auto n = nullptr; return n; // Problem (1) } int* foo_2() { volatile auto a = bar(); // Problem (2) return a; } ``` There are 2 additional places, where std::nullptr_t causes side effects. (1) nullptr_t identical conversion produces: mov QWORD PTR [rsp-8], 0 mov rax, QWORD PTR [rsp-8] // load n ret (2) Initialization by not constant expression: call bar() mov QWORD PTR [rsp+8], rax mov rax, QWORD PTR [rsp+8] xor eax, eax --- diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index cbed847b343..24c1ceb4404 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -218,8 +218,11 @@ 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: + If T is cv std::nullptr_t, the result is a null pointer constant. */ + return ((TREE_SIDE_EFFECTS (expr) && !CONVERT_EXPR_P (expr)) + ? build2 (COMPOUND_EXPR, type, expr, val) + : val); } else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form)) { @@ -743,8 +746,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags, { if (complain & tf_warning) maybe_warn_zero_as_null_pointer_constant (e, loc); - - if (!TREE_SIDE_EFFECTS (e)) + /* C++ [conv.lval]p3: + Convert expr from nullptr to nullptr doesn't have side effect. */ + if (!TREE_SIDE_EFFECTS (e) || CONVERT_EXPR_P (expr)) return nullptr_node; } diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc index ac0fefa24f2..9c7866d319f 100644 --- a/gcc/cp/typeck2.cc +++ b/gcc/cp/typeck2.cc @@ -770,6 +770,15 @@ split_nonconstant_init (tree dest, tree init) && array_of_runtime_bound_p (TREE_TYPE (dest))) code = build_vec_init (dest, NULL_TREE, init, /*value-init*/false, /*from array*/1, tf_warning_or_error); + else if (TREE_CODE (TREE_TYPE(init)) == NULLPTR_TYPE) + { + /* C++ [conv.lval]p3: + If T is cv std::nullptr_t, the result is a null pointer constant. */ + tree val = build_int_cst(TREE_TYPE(dest), 0); + tree ie = cp_build_init_expr(dest, val); + // remain expr with side effect + code = add_stmt_to_compound(init, ie); + } else code = cp_build_init_expr (dest, init);