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 <ja...@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