Commit f2acb8ad by Jason Merrill Committed by Jason Merrill

re PR c++/63885 (ICE in static assert of constexpr forwarding xvalue container…

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
parent 69eb4fde
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.
......
......@@ -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)
......
......@@ -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);
......
// 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
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