2014-10-10 Jason Merrill <jason@redhat.com>
+ PR c++/62115
+ * class.c (build_base_path): Preserve rvalueness.
+ * call.c (convert_like_real) [ck_base]: Let convert_to_base handle &/*.
+ * rtti.c (build_dynamic_cast_1): Call convert_to_reference later.
+
PR c++/63194
* method.c (defaulted_late_check): Call maybe_instantiate_noexcept.
/* We are going to bind a reference directly to a base-class
subobject of EXPR. */
/* Build an expression for `*((base*) &expr)'. */
- expr = cp_build_addr_expr (expr, complain);
- expr = convert_to_base (expr, build_pointer_type (totype),
+ expr = convert_to_base (expr, totype,
!c_cast_p, /*nonnull=*/true, complain);
- expr = cp_build_indirect_ref (expr, RO_IMPLICIT_CONVERSION, complain);
return expr;
}
int want_pointer = TYPE_PTR_P (TREE_TYPE (expr));
bool has_empty = false;
bool virtual_access;
+ bool rvalue = false;
if (expr == error_mark_node || binfo == error_mark_node || !binfo)
return error_mark_node;
}
if (!want_pointer)
- /* This must happen before the call to save_expr. */
- expr = cp_build_addr_expr (expr, complain);
+ {
+ rvalue = !real_lvalue_p (expr);
+ /* This must happen before the call to save_expr. */
+ expr = cp_build_addr_expr (expr, complain);
+ }
else
expr = mark_rvalue_use (expr);
|| in_template_function ())
{
expr = build_nop (ptr_target_type, expr);
- if (!want_pointer)
- expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
- return expr;
+ goto indout;
}
/* If we're in an NSDMI, we don't have the full constructor context yet
{
expr = build1 (CONVERT_EXPR, ptr_target_type, expr);
CONVERT_EXPR_VBASE_PATH (expr) = true;
- if (!want_pointer)
- expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
- return expr;
+ goto indout;
}
/* Do we need to check for a null pointer? */
{
expr = cp_build_indirect_ref (expr, RO_NULL, complain);
expr = build_simple_base_path (expr, binfo);
+ if (rvalue)
+ expr = move (expr);
if (want_pointer)
expr = build_address (expr);
target_type = TREE_TYPE (expr);
else
null_test = NULL;
+ indout:
if (!want_pointer)
- expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+ {
+ expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+ if (rvalue)
+ expr = move (expr);
+ }
out:
if (null_test)
errstr = _("source is of incomplete class type");
goto fail;
}
-
- /* Apply trivial conversion T -> T& for dereferenced ptrs. */
- expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
- LOOKUP_NORMAL, NULL_TREE, complain);
}
/* The dynamic_cast operator shall not cast away constness. */
return build_static_cast (type, expr, complain);
}
+ /* Apply trivial conversion T -> T& for dereferenced ptrs. */
+ if (tc == REFERENCE_TYPE)
+ expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,
+ LOOKUP_NORMAL, NULL_TREE, complain);
+
/* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
if (TYPE_POLYMORPHIC_P (TREE_TYPE (exprtype)))
{
// { dg-do run }
extern "C" void abort ();
+bool ok = false;
struct B {
B() {}
- B(const B& b) { abort (); }
+ B(const B& b) { ok = true; }
};
struct D : public B {
int main () {
b = (true ? f() : b);
+ return !ok;
}
--- /dev/null
+// PR c++/62115
+
+struct A {};
+struct B : A {};
+
+struct C
+{
+ C(A& a = B()) {} // { dg-error "rvalue" }
+};
+
+C c; // { dg-error "" }