* C++ PATCH for c++/78358 (decltype and decomposition)
@ 2016-11-15 16:32 Jason Merrill
2016-11-16 21:29 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Jason Merrill @ 2016-11-15 16:32 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 368 bytes --]
OK, (hopefully) one more patch for decltype and C++17 decomposition
declarations. I hadn't been thinking that "referenced type" meant to
look through references in the tuple case, since other parts of
[dcl.decomp] define "the referenced type" directly, but that does seem
to be how it's used elsewhere in the standard.
Tested x86_64-pc-linux-gnu, applying to trunk.
[-- Attachment #2: 78358.diff --]
[-- Type: text/plain, Size: 3597 bytes --]
commit 113051a8a3e231bb4003831a2f595cd8788eec64
Author: Jason Merrill <jason@redhat.com>
Date: Tue Nov 15 10:50:00 2016 -0500
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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index edcd3b4..634efc9 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 29f5233..dc5ad13 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 0000000..a5b686a
--- /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 ();
+}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: C++ PATCH for c++/78358 (decltype and decomposition)
2016-11-15 16:32 C++ PATCH for c++/78358 (decltype and decomposition) Jason Merrill
@ 2016-11-16 21:29 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2016-11-16 21:29 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 675 bytes --]
On Tue, Nov 15, 2016 at 11:31 AM, Jason Merrill <jason@redhat.com> wrote:
> OK, (hopefully) one more patch for decltype and C++17 decomposition
> declarations. I hadn't been thinking that "referenced type" meant to
> look through references in the tuple case, since other parts of
> [dcl.decomp] define "the referenced type" directly, but that does seem
> to be how it's used elsewhere in the standard.
Nope, that wasn't right, either. The tuple section of [dcl.decomp]
also defines "the referenced type" in a way that makes it impossible
to determine from the actual type of the variable, so we need to store
it somewhere.
Tested x86_64-pc-linux-gnu, applying to trunk.
[-- Attachment #2: decomp-type.diff --]
[-- Type: text/plain, Size: 3979 bytes --]
commit 235535a2ee99c30292f8f964a3759fbeb6067e45
Author: Jason Merrill <jason@redhat.com>
Date: Tue Nov 15 22:22:34 2016 -0500
Fix tuple decomposition decltype.
* decl.c (store_decomp_type, lookup_decomp_type): New.
(cp_finish_decomp): Call store_decomp_type.
* semantics.c (finish_decltype_type): Call lookup_decomp_type.
* cp-tree.h: Declare lookup_decomp_type.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0dcb897..cb1b9fa 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5808,6 +5808,7 @@ extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int,
extern void start_decl_1 (tree, bool);
extern bool check_array_initializer (tree, tree, tree);
extern void cp_finish_decl (tree, tree, bool, tree, int);
+extern tree lookup_decomp_type (tree);
extern void cp_finish_decomp (tree, tree, unsigned int);
extern int cp_complete_array_type (tree *, tree, bool);
extern int cp_complete_array_type_or_error (tree *, tree, bool, tsubst_flags_t);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 23ba087..c54a2de 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7293,6 +7293,22 @@ get_tuple_decomp_init (tree decl, unsigned i)
}
}
+/* It's impossible to recover the decltype of a tuple decomposition variable
+ based on the actual type of the variable, so store it in a hash table. */
+static GTY(()) hash_map<tree,tree> *decomp_type_table;
+static void
+store_decomp_type (tree v, tree t)
+{
+ if (!decomp_type_table)
+ decomp_type_table = hash_map<tree,tree>::create_ggc (13);
+ decomp_type_table->put (v, t);
+}
+tree
+lookup_decomp_type (tree v)
+{
+ return *decomp_type_table->get (v);
+}
+
/* Finish a decomposition declaration. DECL is the underlying declaration
"e", FIRST is the head of a chain of decls for the individual identifiers
chained through DECL_CHAIN in reverse order and COUNT is the number of
@@ -7467,6 +7483,8 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
v[i]);
goto error_out;
}
+ /* Save the decltype away before reference collapse. */
+ store_decomp_type (v[i], eltype);
eltype = cp_build_reference_type (eltype, !lvalue_p (init));
TREE_TYPE (v[i]) = eltype;
layout_decl (v[i], 0);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index dc5ad13..96c67a5 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8902,7 +8902,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
return unlowered_expr_type (expr);
else
/* Expr is a reference variable for the tuple case. */
- return non_reference (TREE_TYPE (expr));
+ return lookup_decomp_type (expr);
}
switch (TREE_CODE (expr))
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp17.C b/gcc/testsuite/g++.dg/cpp1z/decomp17.C
new file mode 100644
index 0000000..484094b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp17.C
@@ -0,0 +1,15 @@
+// { dg-options -std=c++1z }
+
+#include <tuple>
+
+template <typename, typename> struct same_type;
+template <typename T> struct same_type<T, T> {};
+
+int main() {
+ int i;
+ std::tuple<int,int&,int&&> tuple = { 1, i, 1 };
+ auto &[v, r, rr] = tuple;
+ same_type<decltype(v), int>{};
+ same_type<decltype(r), int&>{};
+ same_type<decltype(rr), int&&>{};
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index 6a98b6e..0a82a4a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2457,8 +2457,7 @@ extern void decl_value_expr_insert (tree, tree);
/* In a VAR_DECL or PARM_DECL, the location at which the value may be found,
if transformations have made this more complicated than evaluating the
- decl itself. This should only be used for debugging; once this field has
- been set, the decl itself may not legitimately appear in the function. */
+ decl itself. */
#define DECL_HAS_VALUE_EXPR_P(NODE) \
(TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, RESULT_DECL) \
->decl_common.decl_flag_2)
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2016-11-16 21:29 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-15 16:32 C++ PATCH for c++/78358 (decltype and decomposition) Jason Merrill
2016-11-16 21:29 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).