On Sat, May 17, 2014 at 10:15 AM, Richard Sandiford
<[email protected]> wrote:
> The main thing keeping zero-precision wide-ints alive was void_zero_node,
> a tree used in the C and C++ frontends that has type VOID_TYPE but code
> INTEGER_CST.
>
> Richard B. asked me to replace the INTEGER_CST with a new constant type,
> here called VOID_CST. Most of it is straight-forward. The one perhaps
> controversial bit is that C++ uses void_(zero_)node to represent dummy
> objects when e.g. taking the address of a member function without an
> associated object. IIUC the node used in this situation needs to be
> distinct from anything that could occur in user code and therefore couldn't
> be a simple null pointer.
>
> This reaches the gimplifier in cases like
> g++.old-deja/g++.brendan/operators4.C. I chose to handle it in the
> gimplifier, since void_zero_node was previously handled there too,
> although perhaps by accident. If you object strongly to this then
> I'll need pretty detailed instructions about what to do instead,
> i.e. exactly which parts of the C++ front end need to be changed
> in order for dummy objects never to escape.
I suppose it reaches the gimplifier because it's not handled in
fold-const.c:fold_convert_loc while the INTEGER_CST void_zero_node
was (through fold_convert_const).
That said, only handling (T)void_cst in gimplification looks like
a hack. If necessary we'd want to treat it as construct-T-with-zero-value
consistently.
> I wasn't sure if any errors could ever print void_(zero_)node,
> so I tested the pretty-printing routines by adding fake errors
> after convert_to_void, etc.
>
> Tested on x86_64-linux-gnu. OK to install?
>
> I haven't yet tested whether this makes zero precision go away completely,
> but will do soon.
The middle-end changes look good to me, but as this mainly affects
the C++ frontend I'd like a C++ maintainer to chime in.
Thanks,
Richard.
> Thanks,
> Richard
>
>
> gcc/
> * tree.def (VOID_CST): New.
> * tree-core.h (TI_VOID): New.
> * tree.h (void_node): New.
> * tree.c (tree_node_structure_for_code, tree_code_size)
> (iterative_hash_expr): Handle VOID_CST.
> (build_common_tree_nodes): Initialize void_node.
> * gimplify.c (gimplify_conversion): Handle void_node.
>
> gcc/c-family/
> * c-common.h (CTI_VOID_ZERO, void_zero_node): Delete.
> * c-common.c (c_common_nodes_and_builtins): Don't initialize
> void_zero_node.
> * c-pretty-print.c (pp_c_void_constant): New function.
> (c_pretty_printer::constant, c_pretty_printer::primary_expression)
> (c_pretty_printer::expression): Handle VOID_CST.
> * cilk.c (extract_free_variables): Likewise.
> * c-ubsan.c (ubsan_instrument_division, ubsan_instrument_shift)
> (ubsan_instrument_vla): Use void_node instead of void_zero_node.
>
> gcc/c/
> * c-array-notation.c (expand_array_notations): Use void_node
> instead of void_zero_node.
>
> gcc/cp/
> * cvt.c (convert_to_void): Use void_node instead of void_zero_node.
> * cp-array-notation.c (replace_invariant_exprs): Likewise.
> (expand_array_notation): Handle VOID_CST.
> * error.c (dump_expr): Likewise.
> * cxx-pretty-print.c (cxx_pretty_printer::primary_expression)
> (cxx_pretty_printer::expression): Likewise.
> (pp_cxx_new_expression): Use void_node instead of void_zero_node.
> * decl.c (register_dtor_fn): Likewise.
> * init.c (build_raw_new_expr, build_new_1, build_vec_init)
> (build_delete, push_base_cleanups): Likewise.
> * mangle.c (write_expression): Likewise.
> * semantics.c (finish_break_stmt, empty_expr_stmt_p): Likewise.
> * pt.c (tsubst_decl, tsubst_copy_and_build): Likewise.
> (tsubst, tsubst_copy, build_non_dependent_expr): Handle VOID_CST.
> * tree.c (cp_tree_equal): Likewise.
> (build_dummy_object, is_dummy_object, stabilize_expr): Use void_node
> instead of void_zero_node.
> * typeck.c (check_return_expr): Likewise.
> * typeck2.c (build_functional_cast): Likewise.
>
> Index: gcc/tree.def
> ===================================================================
> --- gcc/tree.def 2014-05-06 18:39:10.534452560 +0100
> +++ gcc/tree.def 2014-05-17 08:49:49.457516579 +0100
> @@ -257,6 +257,8 @@ DEFTREECODE (LANG_TYPE, "lang_type", tcc
>
> /* First, the constants. */
>
> +DEFTREECODE (VOID_CST, "void_cst", tcc_constant, 0)
> +
> /* Contents are in an array of HOST_WIDE_INTs.
>
> We often access these constants both in their native precision and
> Index: gcc/tree-core.h
> ===================================================================
> --- gcc/tree-core.h 2014-05-06 18:39:14.152493199 +0100
> +++ gcc/tree-core.h 2014-05-17 08:49:49.457516579 +0100
> @@ -410,6 +410,8 @@ enum tree_index {
> TI_UINT32_TYPE,
> TI_UINT64_TYPE,
>
> + TI_VOID,
> +
> TI_INTEGER_ZERO,
> TI_INTEGER_ONE,
> TI_INTEGER_THREE,
> Index: gcc/tree.h
> ===================================================================
> --- gcc/tree.h 2014-05-13 07:54:45.416524663 +0100
> +++ gcc/tree.h 2014-05-17 08:49:49.458516588 +0100
> @@ -3245,6 +3245,8 @@ #define uint16_type_node global_trees[T
> #define uint32_type_node global_trees[TI_UINT32_TYPE]
> #define uint64_type_node global_trees[TI_UINT64_TYPE]
>
> +#define void_node global_trees[TI_VOID]
> +
> #define integer_zero_node global_trees[TI_INTEGER_ZERO]
> #define integer_one_node global_trees[TI_INTEGER_ONE]
> #define integer_three_node global_trees[TI_INTEGER_THREE]
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c 2014-05-13 07:54:45.415524654 +0100
> +++ gcc/tree.c 2014-05-17 08:49:49.460516606 +0100
> @@ -383,6 +383,7 @@ tree_node_structure_for_code (enum tree_
> switch (code)
> {
> /* tcc_constant cases. */
> + case VOID_CST: return TS_TYPED;
> case INTEGER_CST: return TS_INT_CST;
> case REAL_CST: return TS_REAL_CST;
> case FIXED_CST: return TS_FIXED_CST;
> @@ -652,6 +653,7 @@ tree_code_size (enum tree_code code)
> case tcc_constant: /* a constant */
> switch (code)
> {
> + case VOID_CST: return sizeof (struct tree_typed);
> case INTEGER_CST: gcc_unreachable ();
> case REAL_CST: return sizeof (struct tree_real_cst);
> case FIXED_CST: return sizeof (struct tree_fixed_cst);
> @@ -7360,6 +7362,8 @@ iterative_hash_expr (const_tree t, hashv
> {
> /* Alas, constants aren't shared, so we can't rely on pointer
> identity. */
> + case VOID_CST:
> + return iterative_hash_hashval_t (0, val);
> case INTEGER_CST:
> for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
> val = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), val);
> @@ -9631,6 +9635,9 @@ build_common_tree_nodes (bool signed_cha
> TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
> TYPE_USER_ALIGN (void_type_node) = 0;
>
> + void_node = make_node (VOID_CST);
> + TREE_TYPE (void_node) = void_type_node;
> +
> null_pointer_node = build_int_cst (build_pointer_type (void_type_node), 0);
> layout_type (TREE_TYPE (null_pointer_node));
>
> Index: gcc/gimplify.c
> ===================================================================
> --- gcc/gimplify.c 2014-05-13 07:54:48.140550695 +0100
> +++ gcc/gimplify.c 2014-05-17 08:49:49.475516741 +0100
> @@ -1681,7 +1681,15 @@ gimplify_conversion (tree *expr_p)
> /* Then strip away all but the outermost conversion. */
> STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
>
> - /* And remove the outermost conversion if it's useless. */
> + /* Support C++-style dummy objects, in which void_zero is
> + cast to a pointer type. We treat these as null pointers. */
> + if (TREE_OPERAND (*expr_p, 0) == void_node)
> + {
> + gcc_checking_assert (POINTER_TYPE_P (TREE_TYPE (*expr_p)));
> + *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0);
> + }
> +
> + /* Remove the outermost conversion if it's useless. */
> if (tree_ssa_useless_type_conversion (*expr_p))
> *expr_p = TREE_OPERAND (*expr_p, 0);
>
> Index: gcc/c-family/c-common.h
> ===================================================================
> --- gcc/c-family/c-common.h 2014-05-08 21:24:01.274683122 +0100
> +++ gcc/c-family/c-common.h 2014-05-17 08:49:49.460516606 +0100
> @@ -297,8 +297,6 @@ enum c_tree_index
> CTI_C99_FUNCTION_NAME_DECL,
> CTI_SAVED_FUNCTION_NAME_DECLS,
>
> - CTI_VOID_ZERO,
> -
> CTI_NULL,
>
> CTI_MAX
> @@ -430,9 +428,6 @@ #define pretty_function_name_decl_node c
> #define c99_function_name_decl_node
> c_global_trees[CTI_C99_FUNCTION_NAME_DECL]
> #define saved_function_name_decls
> c_global_trees[CTI_SAVED_FUNCTION_NAME_DECLS]
>
> -/* A node for `((void) 0)'. */
> -#define void_zero_node c_global_trees[CTI_VOID_ZERO]
> -
> /* The node for C++ `__null'. */
> #define null_node c_global_trees[CTI_NULL]
>
> Index: gcc/c-family/c-common.c
> ===================================================================
> --- gcc/c-family/c-common.c 2014-05-11 21:21:30.400588654 +0100
> +++ gcc/c-family/c-common.c 2014-05-17 08:49:49.462516624 +0100
> @@ -5524,10 +5524,6 @@ c_common_nodes_and_builtins (void)
> TYPE_NAME (void_type_node) = void_name;
> }
>
> - /* This node must not be shared. */
> - void_zero_node = make_int_cst (1, 1);
> - TREE_TYPE (void_zero_node) = void_type_node;
> -
> void_list_node = build_void_list_node ();
>
> /* Make a type to be the domain of a few array types
> Index: gcc/c-family/c-pretty-print.c
> ===================================================================
> --- gcc/c-family/c-pretty-print.c 2014-05-06 18:38:50.985234029 +0100
> +++ gcc/c-family/c-pretty-print.c 2014-05-17 08:49:49.463516633 +0100
> @@ -906,6 +906,15 @@ pp_c_string_literal (c_pretty_printer *p
> pp_doublequote (pp);
> }
>
> +/* Pretty-print a VOID_CST (void_node). */
> +
> +static void
> +pp_c_void_constant (c_pretty_printer *pp)
> +{
> + pp_c_type_cast (pp, void_type_node);
> + pp_string (pp, "0");
> +}
> +
> /* Pretty-print an INTEGER literal. */
>
> static void
> @@ -1136,6 +1145,10 @@ c_pretty_printer::constant (tree e)
>
> switch (code)
> {
> + case VOID_CST:
> + pp_c_void_constant (this);
> + break;
> +
> case INTEGER_CST:
> {
> tree type = TREE_TYPE (e);
> @@ -1241,6 +1254,7 @@ c_pretty_printer::primary_expression (tr
> translate_string ("<return-value>");
> break;
>
> + case VOID_CST:
> case INTEGER_CST:
> case REAL_CST:
> case FIXED_CST:
> @@ -2131,6 +2145,10 @@ c_pretty_printer::expression (tree e)
> {
> switch (TREE_CODE (e))
> {
> + case VOID_CST:
> + pp_c_void_constant (this);
> + break;
> +
> case INTEGER_CST:
> pp_c_integer_constant (this, e);
> break;
> Index: gcc/c-family/cilk.c
> ===================================================================
> --- gcc/c-family/cilk.c 2014-05-06 18:38:50.986234040 +0100
> +++ gcc/c-family/cilk.c 2014-05-17 08:49:49.463516633 +0100
> @@ -997,6 +997,7 @@ extract_free_variables (tree t, struct w
> {
> case ERROR_MARK:
> case IDENTIFIER_NODE:
> + case VOID_CST:
> case INTEGER_CST:
> case REAL_CST:
> case FIXED_CST:
> Index: gcc/c-family/c-ubsan.c
> ===================================================================
> --- gcc/c-family/c-ubsan.c 2014-05-01 21:50:09.877008530 +0100
> +++ gcc/c-family/c-ubsan.c 2014-05-17 08:49:49.463516633 +0100
> @@ -95,7 +95,7 @@ ubsan_instrument_division (location_t lo
> tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
> ubsan_encode_value (op1));
> }
> - t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
> + t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
>
> return t;
> }
> @@ -178,7 +178,7 @@ ubsan_instrument_shift (location_t loc,
> tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
> ubsan_encode_value (op1));
> }
> - t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
> + t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
>
> return t;
> }
> @@ -207,7 +207,7 @@ ubsan_instrument_vla (location_t loc, tr
> tt = builtin_decl_explicit (bcode);
> tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size));
> }
> - t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);
> + t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);
>
> return t;
> }
> Index: gcc/c/c-array-notation.c
> ===================================================================
> --- gcc/c/c-array-notation.c 2014-04-22 09:05:21.366691542 +0100
> +++ gcc/c/c-array-notation.c 2014-05-17 08:49:49.460516606 +0100
> @@ -1279,7 +1279,7 @@ expand_array_notations (tree *tp, int *w
> A[x:y:z];
> A[x:y];
> Replace those with just void zero node. */
> - *tp = void_zero_node;
> + *tp = void_node;
> default:
> break;
> }
> Index: gcc/cp/cvt.c
> ===================================================================
> --- gcc/cp/cvt.c 2014-05-13 07:54:45.420524702 +0100
> +++ gcc/cp/cvt.c 2014-05-17 08:49:49.464516642 +0100
> @@ -1285,7 +1285,7 @@ convert_to_void (tree expr, impl_conv_vo
> }
> else
> return error_mark_node;
> - expr = void_zero_node;
> + expr = void_node;
> }
> else if (implicit != ICV_CAST && probe == expr && is_overloaded_fn
> (probe))
> {
> @@ -1415,7 +1415,7 @@ convert_to_void (tree expr, impl_conv_vo
> expr = build1 (CONVERT_EXPR, void_type_node, expr);
> }
> if (! TREE_SIDE_EFFECTS (expr))
> - expr = void_zero_node;
> + expr = void_node;
> return expr;
> }
>
> Index: gcc/cp/cp-array-notation.c
> ===================================================================
> --- gcc/cp/cp-array-notation.c 2014-01-02 22:16:12.356353350 +0000
> +++ gcc/cp/cp-array-notation.c 2014-05-17 08:49:49.464516642 +0100
> @@ -181,7 +181,7 @@ replace_invariant_exprs (tree *node)
> if (VOID_TYPE_P (TREE_TYPE (t)))
> {
> finish_expr_stmt (t);
> - new_var = void_zero_node;
> + new_var = void_node;
> }
> else
> new_var = get_temp_regvar (TREE_TYPE (t), t);
> @@ -1126,6 +1126,7 @@ expand_array_notation_exprs (tree t)
> {
> case ERROR_MARK:
> case IDENTIFIER_NODE:
> + case VOID_CST:
> case INTEGER_CST:
> case REAL_CST:
> case FIXED_CST:
> Index: gcc/cp/error.c
> ===================================================================
> --- gcc/cp/error.c 2014-04-11 09:33:54.568167858 +0100
> +++ gcc/cp/error.c 2014-05-17 08:49:49.465516651 +0100
> @@ -1913,6 +1913,7 @@ dump_expr (cxx_pretty_printer *pp, tree
> pp_cxx_ws_string (pp, M_("<unknown>"));
> break;
>
> + case VOID_CST:
> case INTEGER_CST:
> case REAL_CST:
> case STRING_CST:
> Index: gcc/cp/cxx-pretty-print.c
> ===================================================================
> --- gcc/cp/cxx-pretty-print.c 2014-01-02 22:16:12.811356978 +0000
> +++ gcc/cp/cxx-pretty-print.c 2014-05-17 08:49:49.465516651 +0100
> @@ -403,6 +403,7 @@ cxx_pretty_printer::primary_expression (
> {
> switch (TREE_CODE (t))
> {
> + case VOID_CST:
> case INTEGER_CST:
> case REAL_CST:
> case COMPLEX_CST:
> @@ -690,7 +691,7 @@ pp_cxx_new_expression (cxx_pretty_printe
> pp_left_paren (pp);
> if (TREE_CODE (init) == TREE_LIST)
> pp_c_expression_list (pp, init);
> - else if (init == void_zero_node)
> + else if (init == void_node)
> ; /* OK, empty initializer list. */
> else
> pp->expression (init);
> @@ -1028,6 +1029,7 @@ cxx_pretty_printer::expression (tree t)
> switch (TREE_CODE (t))
> {
> case STRING_CST:
> + case VOID_CST:
> case INTEGER_CST:
> case REAL_CST:
> case COMPLEX_CST:
> Index: gcc/cp/decl.c
> ===================================================================
> --- gcc/cp/decl.c 2014-05-13 07:54:45.418524683 +0100
> +++ gcc/cp/decl.c 2014-05-17 08:49:49.467516669 +0100
> @@ -6830,7 +6830,7 @@ register_dtor_fn (tree decl)
>
> type = TREE_TYPE (decl);
> if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
> - return void_zero_node;
> + return void_node;
>
> /* If we're using "__cxa_atexit" (or "__cxa_thread_atexit" or
> "__aeabi_atexit"), and DECL is a class object, we can just pass the
> @@ -7077,7 +7077,7 @@ expand_static_init (tree decl, tree init
>
> TARGET_EXPR_CLEANUP (begin)
> = build3 (COND_EXPR, void_type_node, flag,
> - void_zero_node,
> + void_node,
> build_call_n (abort_fn, 1, guard_addr));
> CLEANUP_EH_ONLY (begin) = 1;
>
> @@ -8425,7 +8425,7 @@ compute_array_index_type (tree name, tre
> tree comp = build2 (LT_EXPR, boolean_type_node, itype,
> ssize_int (-1));
> comp = build3 (COND_EXPR, void_type_node, comp,
> - throw_bad_array_length (), void_zero_node);
> + throw_bad_array_length (), void_node);
> finish_expr_stmt (comp);
> }
> else if (flag_sanitize & SANITIZE_VLA)
> Index: gcc/cp/init.c
> ===================================================================
> --- gcc/cp/init.c 2014-05-17 07:59:02.511986086 +0100
> +++ gcc/cp/init.c 2014-05-17 08:49:49.468516678 +0100
> @@ -2116,7 +2116,7 @@ build_raw_new_expr (vec<tree, va_gc> *pl
> if (init == NULL)
> init_list = NULL_TREE;
> else if (init->is_empty ())
> - init_list = void_zero_node;
> + init_list = void_node;
> else
> init_list = build_tree_list_vec (init);
>
> @@ -2931,7 +2931,7 @@ build_new_1 (vec<tree, va_gc> **placemen
>
> TARGET_EXPR_CLEANUP (begin)
> = build3 (COND_EXPR, void_type_node, sentry,
> - cleanup, void_zero_node);
> + cleanup, void_node);
>
> end = build2 (MODIFY_EXPR, TREE_TYPE (sentry),
> sentry, boolean_false_node);
> @@ -3594,7 +3594,7 @@ build_vec_init (tree base, tree maxindex
> else
> throw_call = throw_bad_array_new_length ();
> length_check = build3 (COND_EXPR, void_type_node, length_check,
> - throw_call, void_zero_node);
> + throw_call, void_node);
> finish_expr_stmt (length_check);
> }
>
> @@ -4016,7 +4016,7 @@ build_delete (tree otype, tree addr, spe
> }
>
> if (auto_delete != sfk_deleting_destructor)
> - return void_zero_node;
> + return void_node;
>
> return build_op_delete_call (DELETE_EXPR, addr,
> cxx_sizeof_nowarn (type),
> @@ -4104,8 +4104,7 @@ build_delete (tree otype, tree addr, spe
> }
>
> if (ifexp != integer_one_node)
> - expr = build3 (COND_EXPR, void_type_node,
> - ifexp, expr, void_zero_node);
> + expr = build3 (COND_EXPR, void_type_node, ifexp, expr, void_node);
>
> return expr;
> }
> @@ -4150,7 +4149,7 @@ push_base_cleanups (void)
> if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)))
> {
> expr = build3 (COND_EXPR, void_type_node, cond,
> - expr, void_zero_node);
> + expr, void_node);
> finish_decl_cleanup (NULL_TREE, expr);
> }
> }
> Index: gcc/cp/mangle.c
> ===================================================================
> --- gcc/cp/mangle.c 2014-05-17 07:59:02.516986130 +0100
> +++ gcc/cp/mangle.c 2014-05-17 08:49:49.468516678 +0100
> @@ -2812,7 +2812,7 @@ write_expression (tree expr)
> {
> if (init)
> write_string ("pi");
> - if (init && init != void_zero_node)
> + if (init && init != void_node)
> for (t = init; t; t = TREE_CHAIN (t))
> write_expression (TREE_VALUE (t));
> write_char ('E');
> Index: gcc/cp/semantics.c
> ===================================================================
> --- gcc/cp/semantics.c 2014-05-14 16:41:49.734088647 +0100
> +++ gcc/cp/semantics.c 2014-05-17 08:49:49.470516696 +0100
> @@ -1083,7 +1083,7 @@ finish_break_stmt (void)
> block_may_fallthru returns true when given something it does not
> understand. */
> if (!block_may_fallthru (cur_stmt_list))
> - return void_zero_node;
> + return void_node;
> return add_stmt (build_stmt (input_location, BREAK_STMT));
> }
>
> @@ -2095,7 +2095,7 @@ empty_expr_stmt_p (tree expr_stmt)
> {
> tree body = NULL_TREE;
>
> - if (expr_stmt == void_zero_node)
> + if (expr_stmt == void_node)
> return true;
>
> if (expr_stmt)
> Index: gcc/cp/pt.c
> ===================================================================
> --- gcc/cp/pt.c 2014-05-11 21:21:39.253680836 +0100
> +++ gcc/cp/pt.c 2014-05-17 08:49:49.472516714 +0100
> @@ -10908,7 +10908,7 @@ #define RETURN(EXP) do { r = (EXP); goto
> /* Set up DECL_TEMPLATE_INFO so that we can get at the
> NSDMI in perform_member_init. Still set DECL_INITIAL
> so that we know there is one. */
> - DECL_INITIAL (r) = void_zero_node;
> + DECL_INITIAL (r) = void_node;
> gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
> retrofit_lang_decl (r);
> DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
> @@ -12283,6 +12283,7 @@ tsubst (tree t, tree args, tsubst_flags_
> }
> break;
>
> + case VOID_CST:
> case INTEGER_CST:
> case REAL_CST:
> case STRING_CST:
> @@ -13042,6 +13043,10 @@ tsubst_copy (tree t, tree args, tsubst_f
> error ("use %<...%> to expand argument pack");
> return error_mark_node;
>
> + case VOID_CST:
> + gcc_checking_assert (t == void_node && VOID_TYPE_P (TREE_TYPE (t)));
> + return t;
> +
> case INTEGER_CST:
> case REAL_CST:
> case STRING_CST:
> @@ -14566,7 +14571,7 @@ #define RECUR(NODE)
> \
> else
> {
> init_vec = make_tree_vector ();
> - if (init == void_zero_node)
> + if (init == void_node)
> gcc_assert (init_vec != NULL);
> else
> {
> @@ -15222,9 +15227,9 @@ #define RECUR(NODE)
> \
> cur_stmt_expr = old_stmt_expr;
>
> /* If the resulting list of expression statement is empty,
> - fold it further into void_zero_node. */
> + fold it further into void_node. */
> if (empty_expr_stmt_p (stmt_expr))
> - stmt_expr = void_zero_node;
> + stmt_expr = void_node;
>
> RETURN (stmt_expr);
> }
> @@ -21509,9 +21514,11 @@ build_non_dependent_expr (tree expr)
> cannot be used to initialize a "char *". */
> if (TREE_CODE (expr) == STRING_CST)
> return expr;
> - /* Preserve arithmetic constants, as an optimization -- there is no
> + /* Preserve void and arithmetic constants, as an optimization -- there is
> no
> reason to create a new node. */
> - if (TREE_CODE (expr) == INTEGER_CST || TREE_CODE (expr) == REAL_CST)
> + if (TREE_CODE (expr) == VOID_CST
> + || TREE_CODE (expr) == INTEGER_CST
> + || TREE_CODE (expr) == REAL_CST)
> return expr;
> /* Preserve THROW_EXPRs -- all throw-expressions have type "void".
> There is at least one place where we want to know that a
> Index: gcc/cp/tree.c
> ===================================================================
> --- gcc/cp/tree.c 2014-05-11 21:21:39.251680821 +0100
> +++ gcc/cp/tree.c 2014-05-17 08:49:49.473516723 +0100
> @@ -2620,6 +2620,11 @@ cp_tree_equal (tree t1, tree t2)
>
> switch (code1)
> {
> + case VOID_CST:
> + /* There's only a single VOID_CST node, so we should never reach
> + here. */
> + gcc_unreachable ();
> +
> case INTEGER_CST:
> return tree_int_cst_equal (t1, t2);
>
> @@ -2947,7 +2952,7 @@ member_p (const_tree decl)
> tree
> build_dummy_object (tree type)
> {
> - tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
> + tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_node);
> return cp_build_indirect_ref (decl, RO_NULL, tf_warning_or_error);
> }
>
> @@ -2997,7 +3002,7 @@ is_dummy_object (const_tree ob)
> if (INDIRECT_REF_P (ob))
> ob = TREE_OPERAND (ob, 0);
> return (TREE_CODE (ob) == NOP_EXPR
> - && TREE_OPERAND (ob, 0) == void_zero_node);
> + && TREE_OPERAND (ob, 0) == void_node);
> }
>
> /* Returns 1 iff type T is something we want to treat as a scalar type for
> @@ -3775,7 +3780,7 @@ stabilize_expr (tree exp, tree* initp)
> else if (VOID_TYPE_P (TREE_TYPE (exp)))
> {
> init_expr = exp;
> - exp = void_zero_node;
> + exp = void_node;
> }
> /* There are no expressions with REFERENCE_TYPE, but there can be call
> arguments with such a type; just treat it as a pointer. */
> Index: gcc/cp/typeck.c
> ===================================================================
> --- gcc/cp/typeck.c 2014-05-17 07:59:02.511986086 +0100
> +++ gcc/cp/typeck.c 2014-05-17 08:49:49.474516732 +0100
> @@ -8418,7 +8418,7 @@ check_return_expr (tree retval, bool *no
> else
> {
> if (!retval)
> - retval = void_zero_node;
> + retval = void_node;
> auto_node = type_uses_auto (current_function_auto_return_pattern);
> type = do_auto_deduction (current_function_auto_return_pattern,
> retval, auto_node);
> Index: gcc/cp/typeck2.c
> ===================================================================
> --- gcc/cp/typeck2.c 2014-05-06 18:38:58.635319329 +0100
> +++ gcc/cp/typeck2.c 2014-05-17 08:49:49.474516732 +0100
> @@ -1856,7 +1856,7 @@ build_functional_cast (tree exp, tree pa
> if (parms == NULL_TREE)
> {
> if (VOID_TYPE_P (type))
> - return void_zero_node;
> + return void_node;
> return build_value_init (cv_unqualified (type), complain);
> }
>