diff options
author | Jason Merrill <jason@redhat.com> | 2016-11-15 11:32:38 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-11-15 11:32:38 -0500 |
commit | 944608029f851d39523a71949df3ed9148d9ab8f (patch) | |
tree | ebfcdd2df5f06eedf27dc62369acb9819a987cdf | |
parent | 435fd4073884990c845fffaf65dcea10475f3230 (diff) | |
download | gcc-944608029f851d39523a71949df3ed9148d9ab8f.tar.gz |
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
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/decomp12.C | 20 |
4 files changed, 42 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cdac3ce8aa1..8b5fc8117cf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index edcd3b47fa8..634efc9ba5c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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) \ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 29f52333a94..dc5ad13f681 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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: diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp12.C b/gcc/testsuite/g++.dg/cpp1z/decomp12.C new file mode 100644 index 00000000000..a5b686abdf9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp12.C @@ -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 (); +} |