diff options
author | Jason Merrill <jason@redhat.com> | 2014-11-19 17:06:26 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-11-19 17:06:26 -0500 |
commit | f2acb8ad4361b3fa2185ab3177659d1ee9c54a7f (patch) | |
tree | 5f8522922e6a15dcc1d69df83ed7a5b6b0ec3ebc /gcc | |
parent | 69eb4fde588c5c2e4e206aeba9a5a17fcaf5cecb (diff) | |
download | gcc-f2acb8ad4361b3fa2185ab3177659d1ee9c54a7f.zip gcc-f2acb8ad4361b3fa2185ab3177659d1ee9c54a7f.tar.gz gcc-f2acb8ad4361b3fa2185ab3177659d1ee9c54a7f.tar.bz2 |
re PR c++/63885 (ICE in static assert of constexpr forwarding xvalue container member rvalue reference)
PR c++/63885
* constexpr.c (cxx_eval_constant_expression) [PARM_DECL]: Don't
complain yet about a reference.
[TARGET_EXPR]: Handle TARGET_EXPR with addr == true.
[ADDR_EXPR]: Make sure we don't take the address of a CONSTRUCTOR.
(cxx_bind_parameters_in_call): In the new scheme addr is always false.
* typeck.c (build_address): Don't take the address of a CONSTRUCTOR.
From-SVN: r217815
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 14 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-ref8.C | 61 |
4 files changed, 82 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6f947b4..8f21d8b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2014-11-19 Jason Merrill <jason@redhat.com> + PR c++/63885 + * constexpr.c (cxx_eval_constant_expression) [PARM_DECL]: Don't + complain yet about a reference. + [TARGET_EXPR]: Handle TARGET_EXPR with addr == true. + [ADDR_EXPR]: Make sure we don't take the address of a CONSTRUCTOR. + (cxx_bind_parameters_in_call): In the new scheme addr is always false. + * typeck.c (build_address): Don't take the address of a CONSTRUCTOR. + PR c++/57979 * init.c (decl_really_constant_value): Rename from integral_constant_value. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 5268545..41867b8 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1061,6 +1061,7 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, x = ctx->object; x = cp_build_addr_expr (x, tf_warning_or_error); } + bool addr = false; if (parms && DECL_BY_REFERENCE (parms) && !use_new_call) { /* cp_genericize made this a reference for argument passing, but @@ -1071,9 +1072,9 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, gcc_assert (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE); type = TREE_TYPE (type); x = convert_from_reference (x); + addr = true; } - arg = cxx_eval_constant_expression (ctx, x, - TREE_CODE (type) == REFERENCE_TYPE, + arg = cxx_eval_constant_expression (ctx, x, addr, non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p && ctx->quiet) @@ -2854,6 +2855,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = *p; else if (addr) /* Defer in case this is only used for its type. */; + else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) + /* Defer, there's no lvalue->rvalue conversion. */; else if (is_empty_class (TREE_TYPE (t))) { /* If the class is empty, we aren't actually loading anything. */ @@ -2934,6 +2937,12 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (!*non_constant_p) /* Adjust the type of the result to the type of the temporary. */ r = adjust_temp_type (TREE_TYPE (t), r); + if (addr) + { + tree slot = TARGET_EXPR_SLOT (t); + ctx->values->put (slot, r); + return slot; + } break; case INIT_EXPR: @@ -2995,6 +3004,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; + gcc_checking_assert (TREE_CODE (op) != CONSTRUCTOR); /* This function does more aggressive folding than fold itself. */ r = build_fold_addr_expr_with_type (op, TREE_TYPE (t)); if (TREE_CODE (r) == ADDR_EXPR && TREE_OPERAND (r, 0) == oldop) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 53fe67a..7156851 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5305,6 +5305,7 @@ build_address (tree t) { if (error_operand_p (t) || !cxx_mark_addressable (t)) return error_mark_node; + gcc_checking_assert (TREE_CODE (t) != CONSTRUCTOR); t = build_fold_addr_expr (t); if (TREE_CODE (t) != ADDR_EXPR) t = rvalue (t); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref8.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref8.C new file mode 100644 index 0000000..04de9c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref8.C @@ -0,0 +1,61 @@ +// PR c++/63885 +// { dg-do compile { target c++11 } } + +template<class T> struct remove_reference { typedef T type; }; +template<class T> struct remove_reference<T&> { typedef T type; }; +template<class T> struct remove_reference<T&&> { typedef T type; }; + +template<class T> struct is_lvalue_reference { static const bool value = false; }; +template<class T> struct is_lvalue_reference<T&> { static const bool value = true; }; + +template <bool B, class U, class V> struct conditional; +template <class U, class V> struct conditional<true, U, V> { typedef U type; }; +template <class U, class V> struct conditional<false, U, V> { typedef V type; }; + +template<typename _Tp> constexpr _Tp&& +forward(typename remove_reference<_Tp>::type& __t) noexcept +{ return static_cast<_Tp&&>(__t); } + +/////////////////////////////////////////////////////////////////////////////// + +template <typename C> struct member_forward +{ + typedef typename remove_reference <C>::type::type T; + typedef typename conditional + < + is_lvalue_reference <C &&>::value, + T&, + T + >::type type; +}; + +template <typename C> using member_forward_t = typename member_forward <C>::type; + +/////////////////////////////////////////////////////////////////////////////// + +template <int , typename > struct __get; +template < typename T> struct __get <0, T> +{ + constexpr static auto value (T arg) + -> decltype ((forward <member_forward_t <T>> (arg.t))) + { + return forward <member_forward_t <T>> (arg.t); + } +}; + +template <int N, typename T> constexpr auto get (T && arg) + -> decltype (__get <N, T &&>::value (forward <T> (arg))) +{ + return __get <N, T &&>::value (forward <T> (arg)); +} + +/////////////////////////////////////////////////////////////////////////////// + +template <typename T> struct S +{ + typedef T type; + T t; + + template <typename U> constexpr S (U && u) : t (forward <U> (u)) {} +}; +static_assert (get <0> (S <int &&> (1)) == 1, ""); // g++ 4.9 passes, g++ trunk r217559 fails |