Commit d1522e8f by Jason Merrill Committed by Jason Merrill

re PR c++/62115 (ICE with invalid default argument)

	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.

From-SVN: r216124
parent a4b9dcad
2014-10-10 Jason Merrill <jason@redhat.com> 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 PR c++/63194
* method.c (defaulted_late_check): Call maybe_instantiate_noexcept. * method.c (defaulted_late_check): Call maybe_instantiate_noexcept.
......
...@@ -6341,10 +6341,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, ...@@ -6341,10 +6341,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
/* We are going to bind a reference directly to a base-class /* We are going to bind a reference directly to a base-class
subobject of EXPR. */ subobject of EXPR. */
/* Build an expression for `*((base*) &expr)'. */ /* Build an expression for `*((base*) &expr)'. */
expr = cp_build_addr_expr (expr, complain); expr = convert_to_base (expr, totype,
expr = convert_to_base (expr, build_pointer_type (totype),
!c_cast_p, /*nonnull=*/true, complain); !c_cast_p, /*nonnull=*/true, complain);
expr = cp_build_indirect_ref (expr, RO_IMPLICIT_CONVERSION, complain);
return expr; return expr;
} }
......
...@@ -251,6 +251,7 @@ build_base_path (enum tree_code code, ...@@ -251,6 +251,7 @@ build_base_path (enum tree_code code,
int want_pointer = TYPE_PTR_P (TREE_TYPE (expr)); int want_pointer = TYPE_PTR_P (TREE_TYPE (expr));
bool has_empty = false; bool has_empty = false;
bool virtual_access; bool virtual_access;
bool rvalue = false;
if (expr == error_mark_node || binfo == error_mark_node || !binfo) if (expr == error_mark_node || binfo == error_mark_node || !binfo)
return error_mark_node; return error_mark_node;
...@@ -324,8 +325,11 @@ build_base_path (enum tree_code code, ...@@ -324,8 +325,11 @@ build_base_path (enum tree_code code,
} }
if (!want_pointer) 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 else
expr = mark_rvalue_use (expr); expr = mark_rvalue_use (expr);
...@@ -351,9 +355,7 @@ build_base_path (enum tree_code code, ...@@ -351,9 +355,7 @@ build_base_path (enum tree_code code,
|| in_template_function ()) || in_template_function ())
{ {
expr = build_nop (ptr_target_type, expr); expr = build_nop (ptr_target_type, expr);
if (!want_pointer) goto indout;
expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
return expr;
} }
/* If we're in an NSDMI, we don't have the full constructor context yet /* If we're in an NSDMI, we don't have the full constructor context yet
...@@ -364,9 +366,7 @@ build_base_path (enum tree_code code, ...@@ -364,9 +366,7 @@ build_base_path (enum tree_code code,
{ {
expr = build1 (CONVERT_EXPR, ptr_target_type, expr); expr = build1 (CONVERT_EXPR, ptr_target_type, expr);
CONVERT_EXPR_VBASE_PATH (expr) = true; CONVERT_EXPR_VBASE_PATH (expr) = true;
if (!want_pointer) goto indout;
expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
return expr;
} }
/* Do we need to check for a null pointer? */ /* Do we need to check for a null pointer? */
...@@ -402,6 +402,8 @@ build_base_path (enum tree_code code, ...@@ -402,6 +402,8 @@ build_base_path (enum tree_code code,
{ {
expr = cp_build_indirect_ref (expr, RO_NULL, complain); expr = cp_build_indirect_ref (expr, RO_NULL, complain);
expr = build_simple_base_path (expr, binfo); expr = build_simple_base_path (expr, binfo);
if (rvalue)
expr = move (expr);
if (want_pointer) if (want_pointer)
expr = build_address (expr); expr = build_address (expr);
target_type = TREE_TYPE (expr); target_type = TREE_TYPE (expr);
...@@ -478,8 +480,13 @@ build_base_path (enum tree_code code, ...@@ -478,8 +480,13 @@ build_base_path (enum tree_code code,
else else
null_test = NULL; null_test = NULL;
indout:
if (!want_pointer) 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: out:
if (null_test) if (null_test)
......
...@@ -608,10 +608,6 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) ...@@ -608,10 +608,6 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
errstr = _("source is of incomplete class type"); errstr = _("source is of incomplete class type");
goto fail; 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. */ /* The dynamic_cast operator shall not cast away constness. */
...@@ -631,6 +627,11 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) ...@@ -631,6 +627,11 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
return build_static_cast (type, expr, complain); 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). */ /* Otherwise *exprtype must be a polymorphic class (have a vtbl). */
if (TYPE_POLYMORPHIC_P (TREE_TYPE (exprtype))) if (TYPE_POLYMORPHIC_P (TREE_TYPE (exprtype)))
{ {
......
// { dg-do run } // { dg-do run }
extern "C" void abort (); extern "C" void abort ();
bool ok = false;
struct B { struct B {
B() {} B() {}
B(const B& b) { abort (); } B(const B& b) { ok = true; }
}; };
struct D : public B { struct D : public B {
...@@ -21,4 +22,5 @@ D f() { ...@@ -21,4 +22,5 @@ D f() {
int main () { int main () {
b = (true ? f() : b); b = (true ? f() : b);
return !ok;
} }
// PR c++/62115
struct A {};
struct B : A {};
struct C
{
C(A& a = B()) {} // { dg-error "rvalue" }
};
C c; // { dg-error "" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment