diff mbox

[C++] P0490R0 GB 20: decomposition declaration should commit to tuple interpretation early

Message ID 20161208215648.GY3541@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Dec. 8, 2016, 9:56 p.m. UTC
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.



	Jakub
diff mbox

Patch

--- 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 }; };