This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] put all conv-ops onto single overload


Currently the conversion operator member functions are kept on a set of METHOD_VEC slots at the start of the method_vec. These are distinguished by return type.

However, usually we want to grab all the conversion operators to see if one permits a conversion to whatever we're converting to. Usually if one has a conversion to T, the function is 'Foo::operator T () const', it's very rare we overload on the this-quals for a given T.

This patch changes things to have a single overload for all the conversion operators. add_method already had sufficient smarts to deal with different target types on a single overload (because, templates). The lookup_conversions function similarly had to deal with templates, which are already on a single list. So that gets simplified too (it's still rather horrible, for which I can only blame myself).

They are still on a magic slot though, and I'm now using a rather ugly idiom of:
      vec_safe_iterate (methods, CLASSTYPE_FIRST_CONVERSION_SLOT, &fns);
      if (fns && !DECL_CONV_FN_P (OVL_FIRST (fns)))
	fns = NULL_TREE;
      for (ovl_iterator iter (fns); iter; ++iter)
        ...
to get at it. That's temporary, until they get a proper name to be looked up by.

Applied to trunk.

nathan
--
Nathan Sidwell
2017-08-24  Nathan Sidwell  <nathan@acm.org>

	Conversion operators kept on single overload set
	* class.c (add_method): Keep all conv-ops on one slot.
	* name-lookup.c (lookup_conversion_operator): Pull the desired
	conv op out of overload set.
	* search.c (lookup_conversions_r): Lose template/non-template
	distinction.
	(lookup_conversions): Likewise.

Index: class.c
===================================================================
--- class.c	(revision 251316)
+++ class.c	(working copy)
@@ -1014,30 +1014,16 @@ modify_vtable_entry (tree t,
 bool
 add_method (tree type, tree method, bool via_using)
 {
-  unsigned slot;
-  bool template_conv_p = false;
-  bool conv_p;
-  vec<tree, va_gc> *method_vec;
-  bool complete_p;
-  bool insert_p = false;
-  tree current_fns;
-
   if (method == error_mark_node)
     return false;
 
-  complete_p = COMPLETE_TYPE_P (type);
-  conv_p = DECL_CONV_FN_P (method);
-  if (conv_p)
-    template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
-		       && DECL_TEMPLATE_CONV_FN_P (method));
+  bool complete_p = COMPLETE_TYPE_P (type);
+  bool conv_p = DECL_CONV_FN_P (method);
 
-  method_vec = CLASSTYPE_METHOD_VEC (type);
+  vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (type);
   if (!method_vec)
     {
-      /* Make a new method vector.  We start with 8 entries.  We must
-	 allocate at least two (for constructors and destructors), and
-	 we're going to end up with an assignment operator at some
-	 point as well.  */
+      /* Make a new method vector.  We start with 8 entries.  */
       vec_alloc (method_vec, 8);
       CLASSTYPE_METHOD_VEC (type) = method_vec;
     }
@@ -1045,24 +1031,22 @@ add_method (tree type, tree method, bool
   /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc.  */
   grok_special_member_properties (method);
 
+  bool insert_p = true;
+  unsigned slot;
   tree m;
 
-  insert_p = true;
   /* See if we already have an entry with this name.  */
   for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
        vec_safe_iterate (method_vec, slot, &m);
        ++slot)
     {
       m = OVL_FIRST (m);
-      if (template_conv_p)
+      if (conv_p)
 	{
-	  if (TREE_CODE (m) == TEMPLATE_DECL
-	      && DECL_TEMPLATE_CONV_FN_P (m))
+	  if (DECL_CONV_FN_P (m))
 	    insert_p = false;
 	  break;
 	}
-      if (conv_p && !DECL_CONV_FN_P (m))
-	break;
       if (DECL_NAME (m) == DECL_NAME (method))
 	{
 	  insert_p = false;
@@ -1073,7 +1057,8 @@ add_method (tree type, tree method, bool
 	  && DECL_NAME (m) > DECL_NAME (method))
 	break;
     }
-  current_fns = insert_p ? NULL_TREE : (*method_vec)[slot];
+  tree current_fns = insert_p ? NULL_TREE : (*method_vec)[slot];
+  gcc_assert (!DECL_EXTERN_C_P (method));
 
   /* Check to see if we've already got this method.  */
   for (ovl_iterator iter (current_fns); iter; ++iter)
@@ -1216,8 +1201,7 @@ add_method (tree type, tree method, bool
     }
 
   /* A class should never have more than one destructor.  */
-  if (current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
-    return false;
+  gcc_assert (!current_fns || !DECL_DESTRUCTOR_P (method));
 
   current_fns = ovl_insert (method, current_fns, via_using);
 
Index: name-lookup.c
===================================================================
--- name-lookup.c	(revision 251319)
+++ name-lookup.c	(working copy)
@@ -1096,34 +1096,31 @@ lookup_arg_dependent (tree name, tree fn
 static tree
 lookup_conversion_operator (tree class_type, tree type)
 {
-  tree tpls = NULL_TREE;
+  tree convs = NULL_TREE;
 
   if (TYPE_HAS_CONVERSION (class_type))
     {
-      tree fns;
+      tree fns = NULL_TREE;
+      tree tpls = NULL_TREE;
       vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (class_type);
 
-      for (int i = CLASSTYPE_FIRST_CONVERSION_SLOT;
-	   vec_safe_iterate (methods, i, &fns); ++i)
+      vec_safe_iterate (methods, CLASSTYPE_FIRST_CONVERSION_SLOT, &fns);
+      if (fns && !DECL_CONV_FN_P (OVL_FIRST (fns)))
+	fns = NULL_TREE;
+      for (ovl_iterator iter (fns); iter; ++iter)
 	{
-	  /* All the conversion operators come near the beginning of
-	     the class.  Therefore, if FN is not a conversion
-	     operator, there is no matching conversion operator in
-	     CLASS_TYPE.  */
-	  tree fn = OVL_FIRST (fns);
-	  if (!DECL_CONV_FN_P (fn))
-	    break;
-
-	  if (TREE_CODE (fn) == TEMPLATE_DECL)
-	    /* All the templated conversion functions are on the same
-	       slot, so remember it.  */
-	    tpls = fns;
-	  else if (same_type_p (DECL_CONV_FN_TYPE (fn), type))
-	    return fns;
+	  if (same_type_p (DECL_CONV_FN_TYPE (*iter), type))
+	    convs = lookup_add (*iter, convs);
+
+	  if (TREE_CODE (*iter) == TEMPLATE_DECL)
+	    tpls = lookup_add (*iter, tpls);
 	}
+
+      if (!convs)
+	convs = tpls;
     }
 
-  return tpls;
+  return convs;
 }
 
 /* TYPE is a class type. Return the member functions in the method
Index: search.c
===================================================================
--- search.c	(revision 251319)
+++ search.c	(working copy)
@@ -38,8 +38,7 @@ static tree dfs_dcast_hint_post (tree, v
 static tree dfs_debug_mark (tree, void *);
 static int check_hidden_convs (tree, int, int, tree, tree, tree);
 static tree split_conversions (tree, tree, tree, tree);
-static int lookup_conversions_r (tree, int, int,
-				 tree, tree, tree, tree, tree *, tree *);
+static int lookup_conversions_r (tree, int, int, tree, tree, tree *);
 static int look_for_overrides_r (tree, tree);
 static tree lookup_field_r (tree, void *);
 static tree dfs_accessible_post (tree, void *);
@@ -2333,14 +2332,13 @@ split_conversions (tree my_convs, tree p
 }
 
 /* Worker for lookup_conversions.  Lookup conversion functions in
-   BINFO and its children.  VIRTUAL_DEPTH is nonzero, if BINFO is in
-   a morally virtual base, and VIRTUALNESS is nonzero, if we've
-   encountered virtual bases already in the tree walk.  PARENT_CONVS &
-   PARENT_TPL_CONVS are lists of list of conversions within parent
-   binfos.  OTHER_CONVS and OTHER_TPL_CONVS are conversions found
-   elsewhere in the tree.  Return the conversions found within this
-   portion of the graph in CONVS and TPL_CONVS.  Return nonzero is we
-   encountered virtualness.  We keep template and non-template
+   BINFO and its children.  VIRTUAL_DEPTH is nonzero, if BINFO is in a
+   morally virtual base, and VIRTUALNESS is nonzero, if we've
+   encountered virtual bases already in the tree walk.  PARENT_CONVS
+   is a list of conversions within parent binfos.  OTHER_CONVS are
+   conversions found elsewhere in the tree.  Return the conversions
+   found within this portion of the graph in CONVS.  Return nonzero if
+   we encountered virtualness.  We keep template and non-template
    conversions separate, to avoid unnecessary type comparisons.
 
    The located conversion functions are held in lists of lists.  The
@@ -2353,26 +2351,17 @@ split_conversions (tree my_convs, tree p
    is the converted-to type.  */
 
 static int
-lookup_conversions_r (tree binfo,
-		      int virtual_depth, int virtualness,
-		      tree parent_convs, tree parent_tpl_convs,
-		      tree other_convs, tree other_tpl_convs,
-		      tree *convs, tree *tpl_convs)
+lookup_conversions_r (tree binfo, int virtual_depth, int virtualness,
+		      tree parent_convs, tree other_convs, tree *convs)
 {
   int my_virtualness = 0;
   tree my_convs = NULL_TREE;
-  tree my_tpl_convs = NULL_TREE;
   tree child_convs = NULL_TREE;
-  tree child_tpl_convs = NULL_TREE;
-  unsigned i;
-  tree base_binfo;
-  vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
-  tree conv;
 
   /* If we have no conversion operators, then don't look.  */
   if (!TYPE_HAS_CONVERSION (BINFO_TYPE (binfo)))
     {
-      *convs = *tpl_convs = NULL_TREE;
+      *convs = NULL_TREE;
 
       return 0;
     }
@@ -2381,60 +2370,32 @@ lookup_conversions_r (tree binfo,
     virtual_depth++;
 
   /* First, locate the unhidden ones at this level.  */
-  for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
-       vec_safe_iterate (method_vec, i, &conv);
-       ++i)
-    {
-      tree cur = OVL_FIRST (conv);
-
-      if (!DECL_CONV_FN_P (cur))
-	break;
+  vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+  tree conv = NULL_TREE;
+  vec_safe_iterate (method_vec, CLASSTYPE_FIRST_CONVERSION_SLOT, &conv);
+  if (conv && !DECL_CONV_FN_P (OVL_FIRST (conv)))
+    conv = NULL_TREE;
 
-      if (TREE_CODE (cur) == TEMPLATE_DECL)
-	/* Only template conversions can be overloaded, and we must
-	   flatten them out and check each one individually.  */
-	for (ovl_iterator iter (conv); iter; ++iter)
-	  {
-	    tree tpl = *iter;
-	    tree type = DECL_CONV_FN_TYPE (tpl);
+  for (ovl_iterator iter (conv); iter; ++iter)
+    {
+      tree fn = *iter;
+      tree type = DECL_CONV_FN_TYPE (fn);
 
-	    if (check_hidden_convs (binfo, virtual_depth, virtualness,
-				    type, parent_tpl_convs, other_tpl_convs))
-	      {
-		my_tpl_convs = tree_cons (binfo, tpl, my_tpl_convs);
-		TREE_TYPE (my_tpl_convs) = type;
-		if (virtual_depth)
-		  {
-		    TREE_STATIC (my_tpl_convs) = 1;
-		    my_virtualness = 1;
-		  }
-	      }
-	  }
-      else
+      if (TREE_CODE (fn) != TEMPLATE_DECL && type_uses_auto (type))
 	{
-	  tree name = DECL_NAME (cur);
+	  mark_used (fn);
+	  type = DECL_CONV_FN_TYPE (fn);
+	}
 
-	  if (!IDENTIFIER_MARKED (name))
+      if (check_hidden_convs (binfo, virtual_depth, virtualness,
+			      type, parent_convs, other_convs))
+	{
+	  my_convs = tree_cons (binfo, fn, my_convs);
+	  TREE_TYPE (my_convs) = type;
+	  if (virtual_depth)
 	    {
-	      tree type = DECL_CONV_FN_TYPE (cur);
-	      if (type_uses_auto (type))
-		{
-		  mark_used (cur);
-		  type = DECL_CONV_FN_TYPE (cur);
-		}
-
-	      if (check_hidden_convs (binfo, virtual_depth, virtualness,
-				      type, parent_convs, other_convs))
-		{
-		  my_convs = tree_cons (binfo, conv, my_convs);
-		  TREE_TYPE (my_convs) = type;
-		  if (virtual_depth)
-		    {
-		      TREE_STATIC (my_convs) = 1;
-		      my_virtualness = 1;
-		    }
-		  IDENTIFIER_MARKED (name) = 1;
-		}
+	      TREE_STATIC (my_convs) = 1;
+	      my_virtualness = 1;
 	    }
 	}
     }
@@ -2446,41 +2407,27 @@ lookup_conversions_r (tree binfo,
 	TREE_STATIC (parent_convs) = 1;
     }
 
-  if (my_tpl_convs)
-    {
-      parent_tpl_convs = tree_cons (binfo, my_tpl_convs, parent_tpl_convs);
-      if (virtual_depth)
-	TREE_STATIC (parent_tpl_convs) = 1;
-    }
-
   child_convs = other_convs;
-  child_tpl_convs = other_tpl_convs;
 
   /* Now iterate over each base, looking for more conversions.  */
+  unsigned i;
+  tree base_binfo;
   for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
     {
-      tree base_convs, base_tpl_convs;
+      tree base_convs;
       unsigned base_virtualness;
 
       base_virtualness = lookup_conversions_r (base_binfo,
 					       virtual_depth, virtualness,
-					       parent_convs, parent_tpl_convs,
-					       child_convs, child_tpl_convs,
-					       &base_convs, &base_tpl_convs);
+					       parent_convs, child_convs,
+					       &base_convs);
       if (base_virtualness)
 	my_virtualness = virtualness = 1;
       child_convs = chainon (base_convs, child_convs);
-      child_tpl_convs = chainon (base_tpl_convs, child_tpl_convs);
     }
 
-  /* Unmark the conversions found at this level  */
-  for (conv = my_convs; conv; conv = TREE_CHAIN (conv))
-    IDENTIFIER_MARKED (OVL_NAME (TREE_VALUE (conv))) = 0;
-
   *convs = split_conversions (my_convs, parent_convs,
 			      child_convs, other_convs);
-  *tpl_convs = split_conversions (my_tpl_convs, parent_tpl_convs,
-				  child_tpl_convs, other_tpl_convs);
 
   return my_virtualness;
 }
@@ -2497,17 +2444,16 @@ lookup_conversions_r (tree binfo,
 tree
 lookup_conversions (tree type)
 {
-  tree convs, tpl_convs;
-  tree list = NULL_TREE;
+  tree convs;
 
   complete_type (type);
   if (!CLASS_TYPE_P (type) || !TYPE_BINFO (type))
     return NULL_TREE;
 
-  lookup_conversions_r (TYPE_BINFO (type), 0, 0,
-			NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
-			&convs, &tpl_convs);
+  lookup_conversions_r (TYPE_BINFO (type), 0, 0, NULL_TREE, NULL_TREE, &convs);
 
+  tree list = NULL_TREE;
+  
   /* Flatten the list-of-lists */
   for (; convs; convs = TREE_CHAIN (convs))
     {
@@ -2517,19 +2463,6 @@ lookup_conversions (tree type)
 	{
 	  next = TREE_CHAIN (probe);
 
-	  TREE_CHAIN (probe) = list;
-	  list = probe;
-	}
-    }
-
-  for (; tpl_convs; tpl_convs = TREE_CHAIN (tpl_convs))
-    {
-      tree probe, next;
-
-      for (probe = TREE_VALUE (tpl_convs); probe; probe = next)
-	{
-	  next = TREE_CHAIN (probe);
-
 	  TREE_CHAIN (probe) = list;
 	  list = probe;
 	}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]