PR c++/78358 - tuple decomposition decltype

* semantics.c (finish_decltype_type): Strip references for a tuple
	decomposition.
	* cp-tree.h (DECL_DECOMPOSITION_P): False for non-variables.

From-SVN: r242432
This commit is contained in:
Jason Merrill 2016-11-15 11:32:38 -05:00 committed by Jason Merrill
parent 435fd40738
commit 944608029f
4 changed files with 42 additions and 10 deletions

View file

@ -1,5 +1,10 @@
2016-11-15 Jason Merrill <jason@redhat.com>
PR c++/78358
* semantics.c (finish_decltype_type): Strip references for a tuple
decomposition.
* cp-tree.h (DECL_DECOMPOSITION_P): False for non-variables.
* decl2.c (decl_maybe_constant_var_p): References qualify.
* constexpr.c (non_const_var_error): Handle references.
* init.c (constant_value_1): Always check decl_constant_var_p.

View file

@ -3627,10 +3627,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.var_declared_inline_p \
= true)
/* Nonzero if NODE is the artificial VAR_DECL for decomposition
/* Nonzero if NODE is an artificial VAR_DECL for a C++17 decomposition
declaration. */
#define DECL_DECOMPOSITION_P(NODE) \
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) \
(VAR_P (NODE) && DECL_LANG_SPECIFIC (NODE) \
? DECL_LANG_SPECIFIC (NODE)->u.base.decomposition_p \
: false)
#define SET_DECL_DECOMPOSITION_P(NODE) \

View file

@ -8873,14 +8873,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
if (identifier_p (expr))
expr = lookup_name (expr);
/* The decltype rules for decomposition are different from the rules for
member access; in particular, the decomposition decl gets
cv-qualifiers from the aggregate object, whereas decltype of a member
access expr ignores the object. */
if (VAR_P (expr) && DECL_DECOMPOSITION_P (expr)
&& DECL_HAS_VALUE_EXPR_P (expr))
return unlowered_expr_type (DECL_VALUE_EXPR (expr));
if (INDIRECT_REF_P (expr))
/* This can happen when the expression is, e.g., "a.b". Just
look at the underlying operand. */
@ -8898,6 +8890,21 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
/* See through BASELINK nodes to the underlying function. */
expr = BASELINK_FUNCTIONS (expr);
/* 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 non_reference (TREE_TYPE (expr));
}
switch (TREE_CODE (expr))
{
case FIELD_DECL:

View file

@ -0,0 +1,20 @@
// PR c++/78358
// { dg-do run }
// { dg-options -std=c++1z }
#include <tuple>
template <typename, typename> struct same_type;
template <typename T> struct same_type<T, T> {};
int main() {
std::tuple tuple = { 1, 'a', 2.3, true };
auto[i, c, d, b] = tuple;
same_type<std::tuple_element<0, decltype(tuple)>::type, decltype(i)>{};
same_type<decltype(i), int>{};
same_type<decltype(c), char>{};
same_type<decltype(d), double>{};
same_type<decltype(b), bool>{};
if (i != 1 || c != 'a' || d != 2.3 || b != true)
__builtin_abort ();
}