https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81176
Jakub Jelinek changed:
What|Removed |Added
CC||jakub at gcc dot gnu.org,
||jason at gcc dot gnu.org,
||nathan at gcc dot gnu.org
--- Comment #1 from Jakub Jelinek ---
Testcase without any headers:
namespace std {
template struct tuple_size;
template struct tuple_element;
}
struct A {
int i;
template int& get() { return i; }
};
template<> struct std::tuple_size { static const int value = 2; };
template struct std::tuple_element { using type = int; };
template struct same_type;
template struct same_type {};
void
foo (A x)
{
auto [ a, b ] = x;
decltype(auto) c = a;
same_type{};
same_type{};
}
In finish_decltype_type we have code to handle this:
/* decltype of a decomposition name drops references in the tuple case
(unlike decltype of a normal variable) and keeps cv-qualifiers from
the containing object in the other cases (unlike decltype of a member
access expression). */
if (DECL_DECOMPOSITION_P (expr))
{
if (DECL_HAS_VALUE_EXPR_P (expr))
/* Expr is an array or struct subobject proxy, handle
bit-fields properly. */
return unlowered_expr_type (expr);
else
/* Expr is a reference variable for the tuple case. */
return lookup_decomp_type (expr);
}
But for decltype(auto) c = a; we have do_auto_deduction called with init which
is *a:
else if (AUTO_IS_DECLTYPE (auto_node))
{
bool id = (DECL_P (init)
|| ((TREE_CODE (init) == COMPONENT_REF
|| TREE_CODE (init) == SCOPE_REF)
&& !REF_PARENTHESIZED_P (init)));
thus id is false because init is not DECL_P and do_auto_deduction doesn't have
special handling of DECL_DECOMPOSITION_P if id_expression_or_member_access_p
argument is false.
So, shall we for the above DECL_P (init) test test it with
tree rinit = INDIRECT_REF_P (init) ? TREE_OPERAND (init, 0) : init;
or something similar (what about the COMPONENT_REF/SCOPE_REF case? Shall we
pass the INDIRECT_REF to finish_decltype_type if INDIRECT_REF_P (init) or not?