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.
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
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)
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. */
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:
/* 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)
{
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);
--- /dev/null
+// 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