diff mbox series

[C++,DR,2336] Clean up synth walkers first

Message ID 017dd293-b56d-3e57-428d-7f967b0a2dea@acm.org
State New
Headers show
Series [C++,DR,2336] Clean up synth walkers first | expand

Commit Message

Nathan Sidwell Nov. 15, 2018, 1:21 p.m. UTC
This patch cleans up walk_field_subobs, synthesized_method_base_walk & 
synthesized_method_walk.  They use a mixture of old-style 
partially-overlapping booleans /and/ new style special_function_kind 
enumeration.  synthesized_method_walk was determining the booleans from 
sfk and then passing the booleans to synthesized_method_base_walk, but 
both the bools and sfk to walk_field_subobs.  Plus for extra confusion 
walk_field_subobs & synthesized_method_base_walk wanted the same args, 
but in different orders.

All this confusion gets in the way of resolving DR 2336.  This patch 
removes that confusion.  I reorder SFK members to be useful for these 
functions, add a set of new predicates and then adjust the 3 functions 
to use those predicates, drop the bools and consistently order their 
parameters.

Applying to trunk after an x6_64-linux bootstrap.

nathan
diff mbox series

Patch

2018-11-15  Nathan Sidwell  <nathan@acm.org>

	* cp-tree.h (enum special_function_kind): Reorder and comment.
	* method.c (SFK_CTOR_P, SFK_DTOR_P, SFK_ASSIGN_P, SFK_COPY_P)
	(SFK_MOVE_P): New predicates.
	(walk_field_subobs, synthesized_method_base_walk): Drop
	copy_arg_p, move_p, assign_p args.  Use new SFK predicates.  Order
	parameters consistently.
	(synthesized_method_walk): Drop ctor_p, copy_arg_p, move_p,
	assign_p calculations.  Use new SFK predicates.  Adjust calls to
	worker functions.

Index: cp-tree.h
===================================================================
--- cp-tree.h	(revision 266161)
+++ cp-tree.h	(working copy)
@@ -5084,20 +5084,22 @@  enum special_function_kind {
   sfk_none = 0,		   /* Not a special function.  This enumeral
 			      must have value zero; see
 			      special_function_p.  */
+  /* The following are ordered, for use by member synthesis fns.  */
+  sfk_destructor,	   /* A destructor.  */
   sfk_constructor,	   /* A constructor.  */
+  sfk_inheriting_constructor, /* An inheriting constructor */
   sfk_copy_constructor,    /* A copy constructor.  */
   sfk_move_constructor,    /* A move constructor.  */
   sfk_copy_assignment,     /* A copy assignment operator.  */
   sfk_move_assignment,     /* A move assignment operator.  */
-  sfk_destructor,	   /* A destructor.  */
+  /* The following are unordered.  */
   sfk_complete_destructor, /* A destructor for complete objects.  */
   sfk_base_destructor,     /* A destructor for base subobjects.  */
   sfk_deleting_destructor, /* A destructor for complete objects that
 			      deletes the object after it has been
 			      destroyed.  */
   sfk_conversion,	   /* A conversion operator.  */
-  sfk_deduction_guide,	   /* A class template deduction guide.  */
-  sfk_inheriting_constructor /* An inheriting constructor */
+  sfk_deduction_guide	   /* A class template deduction guide.  */
 };
 
 /* The various kinds of linkage.  From [basic.link],
Index: method.c
===================================================================
--- method.c	(revision 266161)
+++ method.c	(working copy)
@@ -1283,15 +1283,26 @@  process_subob_fn (tree fn, tree *spec_p,
     }
 }
 
+/* Categorize various special_function_kinds.  */
+#define SFK_CTOR_P(sfk) \
+  ((sfk) >= sfk_constructor && (sfk) <= sfk_move_constructor)
+#define SFK_DTOR_P(sfk) \
+  ((sfk) == sfk_destructor)
+#define SFK_ASSIGN_P(sfk) \
+  ((sfk) == sfk_copy_assignment || (sfk) == sfk_move_assignment)
+#define SFK_COPY_P(sfk) \
+  ((sfk) == sfk_copy_constructor || (sfk) == sfk_copy_assignment)
+#define SFK_MOVE_P(sfk) \
+  ((sfk) == sfk_move_constructor || (sfk) == sfk_move_assignment)
+
 /* Subroutine of synthesized_method_walk to allow recursion into anonymous
    aggregates.  If DTOR_FROM_CTOR is true, we're walking subobject destructors
    called from a synthesized constructor, in which case we don't consider
    the triviality of the subobject destructor.  */
 
 static void
-walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
-		   int quals, bool copy_arg_p, bool move_p,
-		   bool assign_p, tree *spec_p, bool *trivial_p,
+walk_field_subobs (tree fields, special_function_kind sfk, tree fnname,
+		   int quals, tree *spec_p, bool *trivial_p,
 		   bool *deleted_p, bool *constexpr_p,
 		   bool diag, int flags, tsubst_flags_t complain,
 		   bool dtor_from_ctor)
@@ -1315,7 +1326,7 @@  walk_field_subobs (tree fields, tree fnn
 	break;
 
       mem_type = strip_array_types (TREE_TYPE (field));
-      if (assign_p)
+      if (SFK_ASSIGN_P (sfk))
 	{
 	  bool bad = true;
 	  if (CP_TYPE_CONST_P (mem_type) && !CLASS_TYPE_P (mem_type))
@@ -1419,19 +1430,18 @@  walk_field_subobs (tree fields, tree fnn
 
       if (ANON_AGGR_TYPE_P (mem_type))
 	{
-	  walk_field_subobs (TYPE_FIELDS (mem_type), fnname, sfk, quals,
-			     copy_arg_p, move_p, assign_p, spec_p, trivial_p,
-			     deleted_p, constexpr_p,
+	  walk_field_subobs (TYPE_FIELDS (mem_type), sfk, fnname, quals,
+			     spec_p, trivial_p, deleted_p, constexpr_p,
 			     diag, flags, complain, dtor_from_ctor);
 	  continue;
 	}
 
-      if (copy_arg_p)
+      if (SFK_COPY_P (sfk) || SFK_MOVE_P (sfk))
 	{
 	  int mem_quals = cp_type_quals (mem_type) | quals;
 	  if (DECL_MUTABLE_P (field))
 	    mem_quals &= ~TYPE_QUAL_CONST;
-	  argtype = build_stub_type (mem_type, mem_quals, move_p);
+	  argtype = build_stub_type (mem_type, mem_quals, SFK_MOVE_P (sfk));
 	}
       else
 	argtype = NULL_TREE;
@@ -1449,11 +1459,10 @@  walk_field_subobs (tree fields, tree fnn
    synthesized_method_walk, or its local vars.  */
 
 static tree
-synthesized_method_base_walk (tree binfo, tree base_binfo, 
-			      int quals, bool copy_arg_p,
-			      bool move_p, bool ctor_p,
+synthesized_method_base_walk (tree binfo, tree base_binfo,
+			      special_function_kind sfk, tree fnname, int quals,
 			      tree *inheriting_ctor, tree inherited_parms,
-			      tree fnname, int flags, bool diag,
+			      int flags, bool diag,
 			      tree *spec_p, bool *trivial_p,
 			      bool *deleted_p, bool *constexpr_p)
 {
@@ -1461,8 +1470,8 @@  synthesized_method_base_walk (tree binfo
   tree argtype = NULL_TREE;
   deferring_kind defer = dk_no_deferred;
 
-  if (copy_arg_p)
-    argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, move_p);
+  if (SFK_COPY_P (sfk) || SFK_MOVE_P (sfk))
+    argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, SFK_MOVE_P (sfk));
   else if (inheriting_ctor
 	   && (inherited_binfo
 	       = binfo_inherited_from (binfo, base_binfo, *inheriting_ctor)))
@@ -1495,7 +1504,7 @@  synthesized_method_base_walk (tree binfo
 
   process_subob_fn (rval, spec_p, trivial_p, deleted_p,
 		    constexpr_p, diag, BINFO_TYPE (base_binfo));
-  if (ctor_p &&
+  if (SFK_CTOR_P (sfk) &&
       (!BINFO_VIRTUAL_P (base_binfo)
        || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))))
     {
@@ -1529,9 +1538,13 @@  synthesized_method_walk (tree ctype, spe
 			 bool *constexpr_p, bool diag,
 			 tree *inheriting_ctor, tree inherited_parms)
 {
-  tree binfo, base_binfo, fnname;
+  tree binfo, base_binfo;
   int i;
 
+  /* SFK must be exactly one category.  */
+  gcc_checking_assert (SFK_DTOR_P(sfk) + SFK_CTOR_P(sfk)
+		       + SFK_ASSIGN_P(sfk) == 1);
+
   if (spec_p)
     *spec_p = (cxx_dialect >= cxx11 ? noexcept_true_spec : empty_except_spec);
 
@@ -1556,35 +1569,20 @@  synthesized_method_walk (tree ctype, spe
       *deleted_p = false;
     }
 
-  bool ctor_p = false;
-  bool assign_p = false;
   bool check_vdtor = false;
-  switch (sfk)
-    {
-    case sfk_move_assignment:
-    case sfk_copy_assignment:
-      assign_p = true;
-      fnname = assign_op_identifier;
-      break;
+  tree fnname;
 
-    case sfk_destructor:
+if (SFK_DTOR_P (sfk))
+    {
       check_vdtor = true;
       /* The synthesized method will call base dtors, but check complete
 	 here to avoid having to deal with VTT.  */
       fnname = complete_dtor_identifier;
-      break;
-
-    case sfk_constructor:
-    case sfk_move_constructor:
-    case sfk_copy_constructor:
-    case sfk_inheriting_constructor:
-      ctor_p = true;
-      fnname = complete_ctor_identifier;
-      break;
-
-    default:
-      gcc_unreachable ();
     }
+  else if (SFK_ASSIGN_P (sfk))
+    fnname = assign_op_identifier;
+  else
+    fnname = complete_ctor_identifier;
 
   gcc_assert ((sfk == sfk_inheriting_constructor)
 	      == (inheriting_ctor && *inheriting_ctor != NULL_TREE));
@@ -1601,29 +1599,8 @@  synthesized_method_walk (tree ctype, spe
 	thereof), the assignment operator selected to copy/move that
 	member is a constexpr function.  */
   if (constexpr_p)
-    *constexpr_p = ctor_p || (assign_p && cxx_dialect >= cxx14);
-
-  bool move_p = false;
-  bool copy_arg_p = false;
-  switch (sfk)
-    {
-    case sfk_constructor:
-    case sfk_destructor:
-    case sfk_inheriting_constructor:
-      break;
-
-    case sfk_move_constructor:
-    case sfk_move_assignment:
-      move_p = true;
-      /* FALLTHRU */
-    case sfk_copy_constructor:
-    case sfk_copy_assignment:
-      copy_arg_p = true;
-      break;
-
-    default:
-      gcc_unreachable ();
-    }
+    *constexpr_p = (SFK_CTOR_P (sfk)
+		    || (SFK_ASSIGN_P (sfk) && cxx_dialect >= cxx14));
 
   bool expected_trivial = type_has_trivial_fn (ctype, sfk);
   if (trivial_p)
@@ -1640,7 +1617,7 @@  synthesized_method_walk (tree ctype, spe
      resolution, so a constructor can be trivial even if it would otherwise
      call a non-trivial constructor.  */
   if (expected_trivial
-      && (!copy_arg_p || cxx_dialect < cxx11))
+      && (!(SFK_COPY_P (sfk) || SFK_MOVE_P (sfk)) || cxx_dialect < cxx11))
     {
       if (constexpr_p && sfk == sfk_constructor)
 	{
@@ -1675,19 +1652,17 @@  synthesized_method_walk (tree ctype, spe
   for (binfo = TYPE_BINFO (ctype), i = 0;
        BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
     {
-      if (!assign_p && BINFO_VIRTUAL_P (base_binfo))
+      if (!SFK_ASSIGN_P (sfk) && BINFO_VIRTUAL_P (base_binfo))
 	/* We'll handle virtual bases below.  */
 	continue;
 
-      tree fn = synthesized_method_base_walk (binfo, base_binfo, quals,
-					      copy_arg_p, move_p, ctor_p,
-					      inheriting_ctor,
-					      inherited_parms,
-					      fnname, flags, diag,
-					      spec_p, trivial_p,
+      tree fn = synthesized_method_base_walk (binfo, base_binfo,
+					      sfk, fnname, quals,
+					      inheriting_ctor, inherited_parms,
+					      flags, diag, spec_p, trivial_p,
 					      deleted_p, constexpr_p);
 
-      if (diag && assign_p && move_p
+      if (diag && SFK_ASSIGN_P (sfk) && SFK_MOVE_P (sfk)
 	  && BINFO_VIRTUAL_P (base_binfo)
 	  && fn && TREE_CODE (fn) == FUNCTION_DECL
 	  && move_fn_p (fn) && !trivial_fn_p (fn)
@@ -1716,7 +1691,7 @@  synthesized_method_walk (tree ctype, spe
     }
 
   vec<tree, va_gc> *vbases = CLASSTYPE_VBASECLASSES (ctype);
-  if (assign_p)
+  if (SFK_ASSIGN_P (sfk))
     /* Already examined vbases above.  */;
   else if (vec_safe_is_empty (vbases))
     /* No virtual bases to worry about.  */;
@@ -1734,24 +1709,20 @@  synthesized_method_walk (tree ctype, spe
 	*constexpr_p = false;
 
       FOR_EACH_VEC_ELT (*vbases, i, base_binfo)
-	synthesized_method_base_walk (binfo, base_binfo, quals,
-				      copy_arg_p, move_p, ctor_p,
+	synthesized_method_base_walk (binfo, base_binfo, sfk, fnname, quals,
 				      inheriting_ctor, inherited_parms,
-				      fnname, flags, diag,
-				      spec_p, trivial_p,
-				      deleted_p, constexpr_p);
+				      flags, diag,
+				      spec_p, trivial_p, deleted_p, constexpr_p);
     }
 
   /* Now handle the non-static data members.  */
-  walk_field_subobs (TYPE_FIELDS (ctype), fnname, sfk, quals,
-		     copy_arg_p, move_p, assign_p, spec_p, trivial_p,
-		     deleted_p, constexpr_p,
+  walk_field_subobs (TYPE_FIELDS (ctype), sfk, fnname, quals,
+		     spec_p, trivial_p, deleted_p, constexpr_p,
 		     diag, flags, complain, /*dtor_from_ctor*/false);
-  if (ctor_p)
-    walk_field_subobs (TYPE_FIELDS (ctype), complete_dtor_identifier,
-		       sfk_destructor, TYPE_UNQUALIFIED, false,
-		       false, false, NULL, NULL,
-		       deleted_p, NULL,
+  if (SFK_CTOR_P (sfk))
+    walk_field_subobs (TYPE_FIELDS (ctype), sfk_destructor,
+		       complete_dtor_identifier, TYPE_UNQUALIFIED,
+		       NULL, NULL, deleted_p, NULL,
 		       false, flags, complain, /*dtor_from_ctor*/true);
 
   pop_scope (scope);