The first hunk fixes looking through the array reference; the second fixes looking through the base class conversion. There's more to do to implement DR 1299, but this is a solid improvement from a fairly trivial patch.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit a065c041556f30a685e2d6b02c0486f7e7e77443 Author: Jason Merrill <ja...@redhat.com> Date: Tue May 1 20:23:18 2018 -0400 PR c++/81420 - not extending temporary lifetime. * call.c (extend_ref_init_temps_1): Handle ARRAY_REF. * class.c (build_base_path): Avoid redundant move of an rvalue. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1df4d14dfe6..c100a92f2fb 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -11061,7 +11061,9 @@ extend_ref_init_temps_1 (tree decl, tree init, vec<tree, va_gc> **cleanups) if (TREE_CODE (sub) != ADDR_EXPR) return init; /* Deal with binding to a subobject. */ - for (p = &TREE_OPERAND (sub, 0); TREE_CODE (*p) == COMPONENT_REF; ) + for (p = &TREE_OPERAND (sub, 0); + (TREE_CODE (*p) == COMPONENT_REF + || TREE_CODE (*p) == ARRAY_REF); ) p = &TREE_OPERAND (*p, 0); if (TREE_CODE (*p) == TARGET_EXPR) { diff --git a/gcc/cp/class.c b/gcc/cp/class.c index a9a0fa92727..25753d4c45f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -426,7 +426,7 @@ build_base_path (enum tree_code code, { expr = cp_build_fold_indirect_ref (expr); expr = build_simple_base_path (expr, binfo); - if (rvalue) + if (rvalue && lvalue_p (expr)) expr = move (expr); if (want_pointer) expr = build_address (expr); diff --git a/gcc/testsuite/g++.dg/cpp0x/temp-extend1.C b/gcc/testsuite/g++.dg/cpp0x/temp-extend1.C new file mode 100644 index 00000000000..639f9456573 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/temp-extend1.C @@ -0,0 +1,19 @@ +// PR c++/81420 +// { dg-do run { target c++11 } } + +int d; + +struct A +{ + int i[2]; + ~A() { ++d; }; +}; + +struct B: A {}; + +int main() +{ + const int &r = B().i[0]; + if (d != 0) + __builtin_abort(); +}