* typeck.c (cp_build_fold_indirect_ref): New.
(cp_build_indirect_ref_1): Split out from cp_build_indirect_ref.
Add 'fold' parameter.
* cp-tree.h: Declare cp_build_fold_indirect_ref.
* call.c, class.c, cp-ubsan.c, decl.c, except.c, init.c, lambda.c,
parser.c, rtti.c, tree.c, typeck.c, typeck2.c: Use it.
* parser.c (do_range_for_auto_deduction): Use RO_UNARY_STAR.
(cp_convert_range_for): Likewise.
* typeck2.c (build_x_arrow): Use RO_ARROW.
From-SVN: r254712
2017-11-13 Jason Merrill <jason@redhat.com>
+ Defer folding of *&.
+ * typeck.c (cp_build_fold_indirect_ref): New.
+ (cp_build_indirect_ref_1): Split out from cp_build_indirect_ref.
+ Add 'fold' parameter.
+ * cp-tree.h: Declare cp_build_fold_indirect_ref.
+ * call.c, class.c, cp-ubsan.c, decl.c, except.c, init.c, lambda.c,
+ parser.c, rtti.c, tree.c, typeck.c, typeck2.c: Use it.
+ * parser.c (do_range_for_auto_deduction): Use RO_UNARY_STAR.
+ (cp_convert_range_for): Likewise.
+ * typeck2.c (build_x_arrow): Use RO_ARROW.
+
* cp-ubsan.c (cp_ubsan_check_member_access_r): Fix handling of
INDIRECT_REF of ADDR_EXPR.
if (targ)
arg = targ;
else
- arg = cp_build_indirect_ref (arg, RO_NULL, complain);
+ arg = cp_build_fold_indirect_ref (arg);
/* In C++17 we shouldn't be copying a TARGET_EXPR except into a base
subobject. */
else if ((trivial || TREE_CODE (arg) == TARGET_EXPR)
&& !unsafe_copy_elision_p (fa, arg))
{
- tree to = cp_stabilize_reference (cp_build_indirect_ref (fa,
- RO_NULL,
- complain));
+ tree to = cp_stabilize_reference (cp_build_fold_indirect_ref (fa));
val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
return val;
&& !DECL_DELETED_FN (fn))
{
tree to = cp_stabilize_reference
- (cp_build_indirect_ref (argarray[0], RO_NULL, complain));
+ (cp_build_fold_indirect_ref (argarray[0]));
tree type = TREE_TYPE (to);
tree as_base = CLASSTYPE_AS_BASE (type);
tree arg = argarray[1];
}
else if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
{
- arg = cp_build_indirect_ref (arg, RO_NULL, complain);
+ arg = cp_build_fold_indirect_ref (arg);
val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg);
/* Handle NSDMI that refer to the object being initialized. */
replace_placeholders (arg, to);
return force_target_expr (DECL_CONTEXT (fn), void_node,
no_cleanup_complain);
else
- return cp_build_indirect_ref (argarray[0], RO_NULL, complain);
+ return cp_build_fold_indirect_ref (argarray[0]);
}
}
interesting to the optimizers anyway. */
&& !has_empty)
{
- expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+ expr = cp_build_fold_indirect_ref (expr);
expr = build_simple_base_path (expr, binfo);
if (rvalue)
expr = move (expr);
t = TREE_TYPE (TYPE_VFIELD (current_class_type));
t = build_pointer_type (t);
v_offset = fold_convert (t, current_vtt_parm);
- v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
+ v_offset = cp_build_fold_indirect_ref (v_offset);
}
else
{
if (t == NULL_TREE)
t = expr;
}
- v_offset = build_vfield_ref (cp_build_indirect_ref (t, RO_NULL,
- complain),
+ v_offset = build_vfield_ref (cp_build_fold_indirect_ref (t),
TREE_TYPE (TREE_TYPE (expr)));
}
v_offset = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
v_offset);
- v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
+ v_offset = cp_build_fold_indirect_ref (v_offset);
TREE_CONSTANT (v_offset) = 1;
offset = convert_to_integer (ptrdiff_type_node,
indout:
if (!want_pointer)
{
- expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+ expr = cp_build_fold_indirect_ref (expr);
if (rvalue)
expr = move (expr);
}
in the back end. */
temp = unary_complex_lvalue (ADDR_EXPR, expr);
if (temp)
- expr = cp_build_indirect_ref (temp, RO_NULL, tf_warning_or_error);
+ expr = cp_build_fold_indirect_ref (temp);
return expr;
}
{
tree aref;
- aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, RO_NULL,
- tf_warning_or_error),
+ aref = build_vtbl_ref_1 (cp_build_fold_indirect_ref (instance_ptr),
idx);
/* When using function descriptors, the address of the
ref_operator, tsubst_flags_t);
extern tree cp_build_indirect_ref (tree, ref_operator,
tsubst_flags_t);
+extern tree cp_build_fold_indirect_ref (tree);
extern tree build_array_ref (location_t, tree, tree);
extern tree cp_build_array_ref (location_t, tree, tree,
tsubst_flags_t);
/* Compute the location of the vtpr. */
tree vtbl_ptr
- = build_vfield_ref (cp_build_indirect_ref (base_ptr, RO_NULL,
- tf_warning_or_error),
+ = build_vfield_ref (cp_build_fold_indirect_ref (base_ptr),
TREE_TYPE (binfo));
gcc_assert (vtbl_ptr != error_mark_node);
gcc_assert (TYPE_PTR_P (TREE_TYPE (t)));
cp_function_chain->x_current_class_ref
- = cp_build_indirect_ref (t, RO_NULL, tf_warning_or_error);
+ = cp_build_fold_indirect_ref (t);
/* Set this second to avoid shortcut in cp_build_indirect_ref. */
cp_function_chain->x_current_class_ptr = t;
CLEANUP_EH_ONLY (allocate_expr) = 1;
object = build_nop (build_pointer_type (temp_type), ptr);
- object = cp_build_indirect_ref (object, RO_NULL, tf_warning_or_error);
+ object = cp_build_fold_indirect_ref (object);
/* And initialize the exception object. */
if (CLASS_TYPE_P (temp_type))
base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
subobject, 1, tf_warning_or_error);
expand_aggr_init_1 (subobject, NULL_TREE,
- cp_build_indirect_ref (base_addr, RO_NULL,
- tf_warning_or_error),
+ cp_build_fold_indirect_ref (base_addr),
arguments,
flags,
tf_warning_or_error);
/* Compute the value to use, when there's a VTT. */
vtt_parm = current_vtt_parm;
vtbl2 = fold_build_pointer_plus (vtt_parm, vtt_index);
- vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error);
+ vtbl2 = cp_build_fold_indirect_ref (vtbl2);
vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
/* The actual initializer is the VTT value only in the subobject
}
/* Compute the location of the vtpr. */
- vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL,
- tf_warning_or_error),
+ vtbl_ptr = build_vfield_ref (cp_build_fold_indirect_ref (decl),
TREE_TYPE (binfo));
gcc_assert (vtbl_ptr != error_mark_node);
alloc_node, cookie_ptr);
size_ptr_type = build_pointer_type (sizetype);
cookie_ptr = fold_convert (size_ptr_type, cookie_ptr);
- cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
+ cookie = cp_build_fold_indirect_ref (cookie_ptr);
cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
NEGATE_EXPR, sizetype,
size_in_bytes (sizetype)));
- cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
+ cookie = cp_build_fold_indirect_ref (cookie_ptr);
cookie = build2 (MODIFY_EXPR, sizetype, cookie,
size_in_bytes (elt_type));
cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
the initializer anyway since we're going to throw it away and
rebuild it at instantiation time, so just build up a single
constructor call to get any appropriate diagnostics. */
- init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
+ init_expr = cp_build_fold_indirect_ref (data_addr);
if (type_build_ctor_call (elt_type))
init_expr = build_special_member_call (init_expr,
complete_ctor_identifier,
}
else
{
- init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
+ init_expr = cp_build_fold_indirect_ref (data_addr);
if (type_build_ctor_call (type) && !explicit_value_init_p)
{
{
atype = build_pointer_type (atype);
stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
- stmt_expr = cp_build_indirect_ref (stmt_expr, RO_NULL, complain);
+ stmt_expr = cp_build_fold_indirect_ref (stmt_expr);
TREE_NO_WARNING (stmt_expr) = 1;
}
/* Make sure the destructor is callable. */
if (type_build_dtor_call (type))
{
- expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL,
- complain),
+ expr = build_dtor_call (cp_build_fold_indirect_ref (addr),
sfk_complete_destructor, flags, complain);
if (expr == error_mark_node)
return error_mark_node;
complain);
}
- expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain),
+ expr = build_dtor_call (cp_build_fold_indirect_ref (addr),
auto_delete, flags, complain);
if (expr == error_mark_node)
return error_mark_node;
sizetype, TYPE_SIZE_UNIT (sizetype));
cookie_addr = fold_build_pointer_plus (fold_convert (size_ptr_type, base),
cookie_addr);
- maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, complain);
+ maxindex = cp_build_fold_indirect_ref (cookie_addr);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
{
gcc_assert (POINTER_TYPE_P (type));
type = TREE_TYPE (type);
- initializer = cp_build_indirect_ref (initializer, RO_NULL,
- tf_warning_or_error);
+ initializer = cp_build_fold_indirect_ref (initializer);
}
if (dependent_type_p (type))
if (tree lam = resolvable_dummy_lambda (object))
if (tree cap = lambda_expr_this_capture (lam, add_capture_p))
if (cap != error_mark_node)
- object = build_x_indirect_ref (EXPR_LOCATION (object), cap,
- RO_NULL, tf_warning_or_error);
+ object = build_fold_indirect_ref (cap);
return object;
}
return expression for a deduced return call op to allow for simple
implementation of the conversion operator. */
- tree instance = cp_build_indirect_ref (thisarg, RO_NULL,
- tf_warning_or_error);
+ tree instance = cp_build_fold_indirect_ref (thisarg);
tree objfn = build_min (COMPONENT_REF, NULL_TREE,
instance, DECL_NAME (callop), NULL_TREE);
int nargs = list_length (DECL_ARGUMENTS (callop)) - 1;
{
iter_decl = build_decl (input_location, VAR_DECL, NULL_TREE,
iter_type);
- iter_decl = build_x_indirect_ref (input_location, iter_decl, RO_NULL,
+ iter_decl = build_x_indirect_ref (input_location, iter_decl,
+ RO_UNARY_STAR,
tf_warning_or_error);
TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl),
iter_decl, auto_node);
/* The declaration is initialized with *__begin inside the loop body. */
cp_finish_decl (range_decl,
- build_x_indirect_ref (input_location, begin, RO_NULL,
+ build_x_indirect_ref (input_location, begin, RO_UNARY_STAR,
tf_warning_or_error),
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
/* Clear this first to avoid shortcut in cp_build_indirect_ref. */
current_class_ptr = NULL_TREE;
current_class_ref
- = cp_build_indirect_ref (this_parm, RO_NULL, tf_warning_or_error);
+ = cp_build_fold_indirect_ref (this_parm);
current_class_ptr = this_parm;
}
index = build_int_cst (NULL_TREE,
-2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
- offset = build_vtbl_ref (cp_build_indirect_ref (exp, RO_NULL,
- tf_warning_or_error),
+ offset = build_vtbl_ref (cp_build_fold_indirect_ref (exp),
index);
type = cp_build_qualified_type (ptr_type_node,
/* Otherwise return the type_info for the static type of the expr. */
t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
- return cp_build_indirect_ref (t, RO_NULL, complain);
+ return cp_build_fold_indirect_ref (t);
}
static bool
exp = cp_build_addr_expr (exp, complain);
exp = save_expr (exp);
cond = cp_convert (boolean_type_node, exp, complain);
- exp = cp_build_indirect_ref (exp, RO_NULL, complain);
+ exp = cp_build_fold_indirect_ref (exp);
}
exp = get_tinfo_decl_dynamic (exp, complain);
if (!type)
return error_mark_node;
- return cp_build_indirect_ref (get_tinfo_ptr (type), RO_NULL, complain);
+ return cp_build_fold_indirect_ref (get_tinfo_ptr (type));
}
/* Check whether TEST is null before returning RESULT. If TEST is used in
build_dummy_object (tree type)
{
tree decl = build1 (CONVERT_EXPR, build_pointer_type (type), void_node);
- return cp_build_indirect_ref (decl, RO_NULL, tf_warning_or_error);
+ return cp_build_fold_indirect_ref (decl);
}
/* We've gotten a reference to a member of TYPE. Return *this if appropriate,
exp = cp_build_addr_expr (exp, tf_warning_or_error);
init_expr = get_target_expr (exp);
exp = TARGET_EXPR_SLOT (init_expr);
- exp = cp_build_indirect_ref (exp, RO_NULL, tf_warning_or_error);
+ exp = cp_build_fold_indirect_ref (exp);
if (xval)
exp = move (exp);
}
{
tree temp = unary_complex_lvalue (ADDR_EXPR, object);
if (temp)
- object = cp_build_indirect_ref (temp, RO_NULL, complain);
+ object = cp_build_fold_indirect_ref (temp);
}
/* In [expr.ref], there is an explicit list of the valid choices for
return rval;
}
-/* Helper function called from c-common. */
-tree
-build_indirect_ref (location_t /*loc*/,
- tree ptr, ref_operator errorstring)
-{
- return cp_build_indirect_ref (ptr, errorstring, tf_warning_or_error);
-}
+/* The implementation of the above, and of indirection implied by other
+ constructs. If DO_FOLD is true, fold away INDIRECT_REF of ADDR_EXPR. */
-tree
-cp_build_indirect_ref (tree ptr, ref_operator errorstring,
- tsubst_flags_t complain)
+static tree
+cp_build_indirect_ref_1 (tree ptr, ref_operator errorstring,
+ tsubst_flags_t complain, bool do_fold)
{
tree pointer, type;
+ /* RO_NULL should only be used with the folding entry points below, not
+ cp_build_indirect_ref. */
+ gcc_checking_assert (errorstring != RO_NULL || do_fold);
+
if (ptr == current_class_ptr
|| (TREE_CODE (ptr) == NOP_EXPR
&& TREE_OPERAND (ptr, 0) == current_class_ptr
error ("%qT is not a pointer-to-object type", type);
return error_mark_node;
}
- else if (TREE_CODE (pointer) == ADDR_EXPR
+ else if (do_fold && TREE_CODE (pointer) == ADDR_EXPR
&& same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
/* The POINTER was something like `&x'. We simplify `*&x' to
`x'. */
return error_mark_node;
}
+/* Entry point used by c-common, which expects folding. */
+
+tree
+build_indirect_ref (location_t /*loc*/,
+ tree ptr, ref_operator errorstring)
+{
+ return cp_build_indirect_ref_1 (ptr, errorstring, tf_warning_or_error, true);
+}
+
+/* Entry point used by internal indirection needs that don't correspond to any
+ syntactic construct. */
+
+tree
+cp_build_fold_indirect_ref (tree pointer)
+{
+ return cp_build_indirect_ref_1 (pointer, RO_NULL, tf_warning_or_error, true);
+}
+
+/* Entry point used by indirection needs that correspond to some syntactic
+ construct. */
+
+tree
+cp_build_indirect_ref (tree ptr, ref_operator errorstring,
+ tsubst_flags_t complain)
+{
+ return cp_build_indirect_ref_1 (ptr, errorstring, complain, false);
+}
+
/* This handles expressions of the form "a[i]", which denotes
an array reference.
/* Next extract the vtable pointer from the object. */
vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
instance_ptr);
- vtbl = cp_build_indirect_ref (vtbl, RO_NULL, complain);
+ vtbl = cp_build_fold_indirect_ref (vtbl);
if (vtbl == error_mark_node)
return error_mark_node;
/* Finally, extract the function pointer from the vtable. */
e2 = fold_build_pointer_plus_loc (input_location, vtbl, idx);
- e2 = cp_build_indirect_ref (e2, RO_NULL, complain);
+ e2 = cp_build_fold_indirect_ref (e2);
if (e2 == error_mark_node)
return error_mark_node;
TREE_CONSTANT (e2) = 1;
return expr;
}
- return cp_build_indirect_ref (last_rval, RO_NULL, complain);
+ return cp_build_indirect_ref (last_rval, RO_ARROW, complain);
}
if (complain & tf_error)
value stored in the pointer-to-data-member. */
ptype = build_pointer_type (type);
datum = fold_build_pointer_plus (fold_convert (ptype, datum), component);
- datum = cp_build_indirect_ref (datum, RO_NULL, complain);
+ datum = cp_build_fold_indirect_ref (datum);
if (datum == error_mark_node)
return error_mark_node;