commit 405d150804256f94e63101f35535098c9e74438b Author: Jason Merrill Date: Mon Jul 29 16:12:56 2013 -0400 PR c++/57901 * semantics.c (build_data_member_initialization, constexpr_fn_retval): Use break_out_target_exprs instead of unshare_expr. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f68d386..acdd178 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6016,7 +6016,7 @@ build_data_member_initialization (tree t, vec **vec) || TREE_CODE (t) == MODIFY_EXPR) { member = TREE_OPERAND (t, 0); - init = unshare_expr (TREE_OPERAND (t, 1)); + init = break_out_target_exprs (TREE_OPERAND (t, 1)); } else if (TREE_CODE (t) == CALL_EXPR) { @@ -6024,7 +6024,7 @@ build_data_member_initialization (tree t, vec **vec) /* We don't use build_cplus_new here because it complains about abstract bases. Leaving the call unwrapped means that it has the wrong type, but cxx_eval_constant_expression doesn't care. */ - init = unshare_expr (t); + init = break_out_target_exprs (t); } else if (TREE_CODE (t) == DECL_EXPR) /* Declaring a temporary, don't add it to the CONSTRUCTOR. */ @@ -6261,7 +6261,7 @@ constexpr_fn_retval (tree body) } case RETURN_EXPR: - return unshare_expr (TREE_OPERAND (body, 0)); + return break_out_target_exprs (TREE_OPERAND (body, 0)); case DECL_EXPR: if (TREE_CODE (DECL_EXPR_DECL (body)) == USING_DECL) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-value4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-value4.C new file mode 100644 index 0000000..1fc3738 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-value4.C @@ -0,0 +1,16 @@ +// PR c++/57901 +// { dg-require-effective-target c++11 } + +struct Z { + Z() = default; + Z(Z const&) = default; + constexpr Z(Z&&) {} /* non-trivial (constexpr) move ctor */ +}; + +template +constexpr int fn0(T v) { return 0; } +template +constexpr int fn (T v) { return fn0(v); } + +constexpr auto t0 = fn0(Z()); // OK! +constexpr auto t = fn (Z()); // error! (GCC 4.8.1)