diff --git a/gcc/d/d-codegen.cc b/gcc/d/d-codegen.cc index e62d1f9d3b3..7ca0acffcc4 100644 --- a/gcc/d/d-codegen.cc +++ b/gcc/d/d-codegen.cc @@ -448,6 +448,42 @@ extract_from_method_call (tree t, tree& callee, tree& object) callee = CONSTRUCTOR_ELT (t, 1)->value; } +/* Build a typeof(null) constant of type TYPE. Handles certain special case + conversions, where the underlying type is an aggregate with a nullable + interior pointer. */ + +tree +build_typeof_null_value (Type *type) +{ + Type *tb = type->toBasetype (); + tree value; + + /* For dynamic arrays, set length and pointer fields to zero. */ + if (tb->ty == Tarray) + value = d_array_value (build_ctype (type), size_int (0), null_pointer_node); + + /* For associative arrays, set the pointer field to null. */ + else if (tb->ty == Taarray) + { + tree ctype = build_ctype (type); + gcc_assert (TYPE_ASSOCIATIVE_ARRAY (ctype)); + + value = build_constructor_single (ctype, TYPE_FIELDS (ctype), + null_pointer_node); + } + + /* For delegates, set the frame and function pointer fields to null. */ + else if (tb->ty == Tdelegate) + value = build_delegate_cst (null_pointer_node, null_pointer_node, type); + + /* Simple zero constant for all other types. */ + else + value = build_zero_cst (build_ctype (type)); + + TREE_CONSTANT (value) = 1; + return value; +} + /* Build a dereference into the virtual table for OBJECT to retrieve a function pointer of type FNTYPE at position INDEX. */ diff --git a/gcc/d/d-convert.cc b/gcc/d/d-convert.cc index 0f3cb7ad0c5..e9aa457d852 100644 --- a/gcc/d/d-convert.cc +++ b/gcc/d/d-convert.cc @@ -560,18 +560,12 @@ convert_expr (tree exp, Type *etype, Type *totype) case Tnull: /* Casting from typeof(null) is represented as all zeros. */ - if (tbtype->ty == Tarray) - { - tree ptrtype = build_ctype (tbtype->nextOf ()->pointerTo ()); - return d_array_value (build_ctype (totype), size_int (0), - build_nop (ptrtype, exp)); - } - else if (tbtype->ty == Taarray) - return build_constructor (build_ctype (totype), NULL); - else if (tbtype->ty == Tdelegate) - return build_delegate_cst (exp, null_pointer_node, totype); + result = build_typeof_null_value (totype); - return build_zero_cst (build_ctype (totype)); + /* Make sure the expression is still evaluated if necessary. */ + if (TREE_SIDE_EFFECTS (exp)) + result = compound_expr (exp, result); + break; case Tvector: if (tbtype->ty == Tsarray) diff --git a/gcc/d/d-tree.h b/gcc/d/d-tree.h index adab1d1f892..6ffb0f32a1f 100644 --- a/gcc/d/d-tree.h +++ b/gcc/d/d-tree.h @@ -511,6 +511,7 @@ extern tree delegate_object (tree); extern tree build_delegate_cst (tree, tree, Type *); extern tree build_method_call (tree, tree, Type *); extern void extract_from_method_call (tree, tree &, tree &); +extern tree build_typeof_null_value (Type *); extern tree build_vindex_ref (tree, tree, size_t); extern tree d_save_expr (tree); extern tree stabilize_expr (tree *); diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index fecdffde020..15754a1dc2e 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -2941,33 +2941,7 @@ public: void visit (NullExp *e) { - Type *tb = e->type->toBasetype (); - tree value; - - /* Handle certain special case conversions, where the underlying type is an - aggregate with a nullable interior pointer. */ - if (tb->ty == Tarray) - { - /* For dynamic arrays, set length and pointer fields to zero. */ - value = d_array_value (build_ctype (e->type), size_int (0), - null_pointer_node); - } - else if (tb->ty == Taarray) - { - /* For associative arrays, set the pointer field to null. */ - value = build_constructor (build_ctype (e->type), NULL); - } - else if (tb->ty == Tdelegate) - { - /* For delegates, set the frame and function pointer to null. */ - value = build_delegate_cst (null_pointer_node, - null_pointer_node, e->type); - } - else - value = d_convert (build_ctype (e->type), integer_zero_node); - - TREE_CONSTANT (value) = 1; - this->result_ = value; + this->result_ = build_typeof_null_value (e->type); } /* Build a vector literal. */