This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] P0490R0 GB 20: decomposition declaration should commit to tuple interpretation early
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 8 Dec 2016 22:56:48 +0100
- Subject: [C++ PATCH] P0490R0 GB 20: decomposition declaration should commit to tuple interpretation early
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Issaquah papers have been recently published and there are two
decomp changes. One I've sent a partially working patch privately and am
lost with, the other one is that whenever std::tuple_size<type> is a
complete type, we should commit to the std::tuple* way - so if it is
missing value static data member/enum or it isn't a constant expression
we should just error out instead of trying to decompose as other structs.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Or shall I move the diagnostics from get_tuple_size to the caller (only
return error_mark_node from there)?
2016-12-08 Jakub Jelinek <jakub@redhat.com>
P0490R0 GB 20: decomposition declaration should commit to tuple
interpretation early
* decl.c (get_tuple_size): Add LOC argument, make static. If
inst is error_mark_node or non-complete type, return NULL_TREE,
otherwise if lookup_qualified_name fails or doesn't fold into
INTEGER_CST, complain and return error_mark_node.
(get_tuple_element_type, get_tuple_decomp_init): Make static.
(cp_finish_decomp): Pass LOC to get_tuple_size. If it returns
error_mark_node, fail.
* g++.dg/cpp1z/decomp10.C (f1): Adjust expected diagnostics.
--- gcc/cp/decl.c.jj 2016-12-07 17:19:10.000000000 +0100
+++ gcc/cp/decl.c 2016-12-08 16:52:10.029095252 +0100
@@ -7259,8 +7259,8 @@ find_decomp_class_base (location_t loc,
/* Return std::tuple_size<TYPE>::value. */
-tree
-get_tuple_size (tree type)
+static tree
+get_tuple_size (location_t loc, tree type)
{
tree args = make_tree_vec (1);
TREE_VEC_ELT (args, 0) = type;
@@ -7268,6 +7268,11 @@ get_tuple_size (tree type)
/*in_decl*/NULL_TREE,
/*context*/std_node,
/*entering_scope*/false, tf_none);
+ if (inst == error_mark_node)
+ return NULL_TREE;
+ inst = complete_type (inst);
+ if (!COMPLETE_TYPE_P (inst))
+ return NULL_TREE;
tree val = lookup_qualified_name (inst, get_identifier ("value"),
/*type*/false, /*complain*/false);
if (TREE_CODE (val) == VAR_DECL || TREE_CODE (val) == CONST_DECL)
@@ -7275,12 +7280,16 @@ get_tuple_size (tree type)
if (TREE_CODE (val) == INTEGER_CST)
return val;
else
- return NULL_TREE;
+ {
+ error_at (loc, "%<std::tuple_size<%T>::value%> is not an integral "
+ "constant expression", type);
+ return error_mark_node;
+ }
}
/* Return std::tuple_element<I,TYPE>::type. */
-tree
+static tree
get_tuple_element_type (tree type, unsigned i)
{
tree args = make_tree_vec (2);
@@ -7297,7 +7306,7 @@ get_tuple_element_type (tree type, unsig
/* Return e.get<i>() or get<i>(e). */
-tree
+static tree
get_tuple_decomp_init (tree decl, unsigned i)
{
tree get_id = get_identifier ("get");
@@ -7342,6 +7351,7 @@ store_decomp_type (tree v, tree t)
decomp_type_table = hash_map<tree,tree>::create_ggc (13);
decomp_type_table->put (v, t);
}
+
tree
lookup_decomp_type (tree v)
{
@@ -7500,8 +7510,10 @@ cp_finish_decomp (tree decl, tree first,
DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
}
}
- else if (tree tsize = get_tuple_size (type))
+ else if (tree tsize = get_tuple_size (loc, type))
{
+ if (tsize == error_mark_node)
+ goto error_out;
eltscnt = tree_to_uhwi (tsize);
if (count != eltscnt)
goto cnt_mismatch;
--- gcc/testsuite/g++.dg/cpp1z/decomp10.C.jj 2016-11-15 09:57:00.000000000 +0100
+++ gcc/testsuite/g++.dg/cpp1z/decomp10.C 2016-12-08 16:48:55.833555410 +0100
@@ -7,7 +7,7 @@ namespace std {
struct A1 { int i,j; } a1;
template<> struct std::tuple_size<A1> { };
-void f1() { auto [ x ] = a1; } // { dg-error "decomposes into 2" }
+void f1() { auto [ x ] = a1; } // { dg-error "is not an integral constant expression" }
struct A2 { int i,j; } a2;
template<> struct std::tuple_size<A2> { enum { value = 5 }; };
Jakub