From d1522e8f63167d81f6bd77c5d29ffdba2e6fbe86 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 11 Oct 2014 21:42:31 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 5 +++++ gcc/cp/call.c | 4 +--- gcc/cp/class.c | 25 ++++++++++++++++--------- gcc/cp/rtti.c | 9 +++++---- gcc/testsuite/g++.dg/expr/cond6.C | 4 +++- gcc/testsuite/g++.dg/overload/defarg9.C | 11 +++++++++++ 6 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/overload/defarg9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index acdb354816c..ebb62d277f1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,10 @@ 2014-10-10 Jason Merrill + 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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 76d8eabf33f..8a89aadeaf9 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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 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; } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index b6611870a23..99bfa957f63 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -251,6 +251,7 @@ build_base_path (enum tree_code code, 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; @@ -324,8 +325,11 @@ build_base_path (enum tree_code code, } 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); @@ -351,9 +355,7 @@ build_base_path (enum tree_code code, || 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 @@ -364,9 +366,7 @@ build_base_path (enum tree_code code, { 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? */ @@ -402,6 +402,8 @@ build_base_path (enum tree_code code, { 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); @@ -478,8 +480,13 @@ build_base_path (enum tree_code code, 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) diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 10cc168faf6..762953b38a0 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -608,10 +608,6 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) 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. */ @@ -631,6 +627,11 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t 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). */ if (TYPE_POLYMORPHIC_P (TREE_TYPE (exprtype))) { diff --git a/gcc/testsuite/g++.dg/expr/cond6.C b/gcc/testsuite/g++.dg/expr/cond6.C index 943aa85a963..8f7f084ce54 100644 --- a/gcc/testsuite/g++.dg/expr/cond6.C +++ b/gcc/testsuite/g++.dg/expr/cond6.C @@ -1,10 +1,11 @@ // { 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 { @@ -21,4 +22,5 @@ D f() { int main () { b = (true ? f() : b); + return !ok; } diff --git a/gcc/testsuite/g++.dg/overload/defarg9.C b/gcc/testsuite/g++.dg/overload/defarg9.C new file mode 100644 index 00000000000..401fe0e324c --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/defarg9.C @@ -0,0 +1,11 @@ +// PR c++/62115 + +struct A {}; +struct B : A {}; + +struct C +{ + C(A& a = B()) {} // { dg-error "rvalue" } +}; + +C c; // { dg-error "" }