compiler: remove duplication of Named_object traversal

Adding type parameters was about to add a partial third version.
Remove the duplication to avoid that.

Change-Id: I0f9ca818c9ff030520690c085d9651681b2dae32
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/375234
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/go/gogo.cc b/go/gogo.cc
index 290d294..e2fd509 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -6890,80 +6890,12 @@
 	  | Traverse::traverse_expressions
 	  | Traverse::traverse_types)) != 0)
     {
-      const unsigned int e_or_t = (Traverse::traverse_expressions
-				   | Traverse::traverse_types);
-      const unsigned int e_or_t_or_s = (e_or_t
-					| Traverse::traverse_statements);
       for (Bindings::const_definitions_iterator pb =
 	     this->bindings_->begin_definitions();
 	   pb != this->bindings_->end_definitions();
 	   ++pb)
 	{
-	  int t = TRAVERSE_CONTINUE;
-	  switch ((*pb)->classification())
-	    {
-	    case Named_object::NAMED_OBJECT_CONST:
-	      if ((traverse_mask & Traverse::traverse_constants) != 0)
-		t = traverse->constant(*pb, false);
-	      if (t == TRAVERSE_CONTINUE
-		  && (traverse_mask & e_or_t) != 0)
-		{
-		  Type* tc = (*pb)->const_value()->type();
-		  if (tc != NULL
-		      && Type::traverse(tc, traverse) == TRAVERSE_EXIT)
-		    return TRAVERSE_EXIT;
-		  t = (*pb)->const_value()->traverse_expression(traverse);
-		}
-	      break;
-
-	    case Named_object::NAMED_OBJECT_VAR:
-	    case Named_object::NAMED_OBJECT_RESULT_VAR:
-	      if ((traverse_mask & Traverse::traverse_variables) != 0)
-		t = traverse->variable(*pb);
-	      if (t == TRAVERSE_CONTINUE
-		  && (traverse_mask & e_or_t) != 0)
-		{
-		  if ((*pb)->is_result_variable()
-		      || (*pb)->var_value()->has_type())
-		    {
-		      Type* tv = ((*pb)->is_variable()
-				  ? (*pb)->var_value()->type()
-				  : (*pb)->result_var_value()->type());
-		      if (tv != NULL
-			  && Type::traverse(tv, traverse) == TRAVERSE_EXIT)
-			return TRAVERSE_EXIT;
-		    }
-		}
-	      if (t == TRAVERSE_CONTINUE
-		  && (traverse_mask & e_or_t_or_s) != 0
-		  && (*pb)->is_variable())
-		t = (*pb)->var_value()->traverse_expression(traverse,
-							    traverse_mask);
-	      break;
-
-	    case Named_object::NAMED_OBJECT_FUNC:
-	    case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
-	      go_unreachable();
-
-	    case Named_object::NAMED_OBJECT_TYPE:
-	      if ((traverse_mask & e_or_t) != 0)
-		t = Type::traverse((*pb)->type_value(), traverse);
-	      break;
-
-	    case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
-	    case Named_object::NAMED_OBJECT_UNKNOWN:
-	    case Named_object::NAMED_OBJECT_ERRONEOUS:
-	      break;
-
-	    case Named_object::NAMED_OBJECT_PACKAGE:
-	    case Named_object::NAMED_OBJECT_SINK:
-	      go_unreachable();
-
-	    default:
-	      go_unreachable();
-	    }
-
-	  if (t == TRAVERSE_EXIT)
+	  if ((*pb)->traverse(traverse, false) == TRAVERSE_EXIT)
 	    return TRAVERSE_EXIT;
 	}
     }
@@ -8673,6 +8605,99 @@
     }
 }
 
+// Traverse a Named_object.
+
+int
+Named_object::traverse(Traverse* traverse, bool is_global)
+{
+  const unsigned int traverse_mask = traverse->traverse_mask();
+  const unsigned int e_or_t = (Traverse::traverse_expressions
+			       | Traverse::traverse_types);
+  const unsigned int e_or_t_or_s = (e_or_t
+				    | Traverse::traverse_statements);
+
+  int t = TRAVERSE_CONTINUE;
+  switch (this->classification_)
+    {
+    case Named_object::NAMED_OBJECT_CONST:
+      if ((traverse_mask & Traverse::traverse_constants) != 0)
+	t = traverse->constant(this, is_global);
+      if (t == TRAVERSE_CONTINUE
+	  && (traverse_mask & e_or_t) != 0)
+	{
+	  Type* tc = this->const_value()->type();
+	  if (tc != NULL)
+	    {
+	      if (Type::traverse(tc, traverse) == TRAVERSE_EXIT)
+		return TRAVERSE_EXIT;
+	    }
+	  t = this->const_value()->traverse_expression(traverse);
+	}
+      break;
+
+    case Named_object::NAMED_OBJECT_VAR:
+    case Named_object::NAMED_OBJECT_RESULT_VAR:
+      if ((traverse_mask & Traverse::traverse_variables) != 0)
+	t = traverse->variable(this);
+      if (t == TRAVERSE_CONTINUE
+	  && (traverse_mask & e_or_t) != 0)
+	{
+	  if (this->is_result_variable() || this->var_value()->has_type())
+	    {
+	      Type* tv = (this->is_variable()
+			  ? this->var_value()->type()
+			  : this->result_var_value()->type());
+	      if (tv != NULL)
+		{
+		  if (Type::traverse(tv, traverse) == TRAVERSE_EXIT)
+		    return TRAVERSE_EXIT;
+		}
+	    }
+	}
+      if (t == TRAVERSE_CONTINUE
+	  && (traverse_mask & e_or_t_or_s) != 0
+	  && this->is_variable())
+	t = this->var_value()->traverse_expression(traverse,
+						   traverse_mask);
+      break;
+
+    case Named_object::NAMED_OBJECT_FUNC:
+      if ((traverse_mask & Traverse::traverse_functions) != 0)
+	t = traverse->function(this);
+      if (t == TRAVERSE_CONTINUE
+	  && (traverse_mask
+	      & (Traverse::traverse_variables
+		 | Traverse::traverse_constants
+		 | Traverse::traverse_functions
+		 | Traverse::traverse_blocks
+		 | Traverse::traverse_statements
+		 | Traverse::traverse_expressions
+		 | Traverse::traverse_types)) != 0)
+	t = this->func_value()->traverse(traverse);
+      break;
+
+    case Named_object::NAMED_OBJECT_TYPE:
+      if ((traverse_mask & e_or_t) != 0)
+	t = Type::traverse(this->type_value(), traverse);
+      break;
+
+    case Named_object::NAMED_OBJECT_PACKAGE:
+    case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
+    case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
+    case Named_object::NAMED_OBJECT_UNKNOWN:
+    case Named_object::NAMED_OBJECT_ERRONEOUS:
+      break;
+
+    case Named_object::NAMED_OBJECT_SINK:
+      go_unreachable();
+
+    default:
+      go_unreachable();
+    }
+
+  return t;
+}
+
 // Export a named object.
 
 void
@@ -9198,90 +9223,10 @@
   // new global objects.
   const unsigned int e_or_t = (Traverse::traverse_expressions
 			       | Traverse::traverse_types);
-  const unsigned int e_or_t_or_s = (e_or_t
-				    | Traverse::traverse_statements);
   for (size_t i = 0; i < this->named_objects_.size(); ++i)
     {
       Named_object* p = this->named_objects_[i];
-      int t = TRAVERSE_CONTINUE;
-      switch (p->classification())
-	{
-	case Named_object::NAMED_OBJECT_CONST:
-	  if ((traverse_mask & Traverse::traverse_constants) != 0)
-	    t = traverse->constant(p, is_global);
-	  if (t == TRAVERSE_CONTINUE
-	      && (traverse_mask & e_or_t) != 0)
-	    {
-	      Type* tc = p->const_value()->type();
-	      if (tc != NULL
-		  && Type::traverse(tc, traverse) == TRAVERSE_EXIT)
-		return TRAVERSE_EXIT;
-	      t = p->const_value()->traverse_expression(traverse);
-	    }
-	  break;
-
-	case Named_object::NAMED_OBJECT_VAR:
-	case Named_object::NAMED_OBJECT_RESULT_VAR:
-	  if ((traverse_mask & Traverse::traverse_variables) != 0)
-	    t = traverse->variable(p);
-	  if (t == TRAVERSE_CONTINUE
-	      && (traverse_mask & e_or_t) != 0)
-	    {
-	      if (p->is_result_variable()
-		  || p->var_value()->has_type())
-		{
-		  Type* tv = (p->is_variable()
-			      ? p->var_value()->type()
-			      : p->result_var_value()->type());
-		  if (tv != NULL
-		      && Type::traverse(tv, traverse) == TRAVERSE_EXIT)
-		    return TRAVERSE_EXIT;
-		}
-	    }
-	  if (t == TRAVERSE_CONTINUE
-	      && (traverse_mask & e_or_t_or_s) != 0
-	      && p->is_variable())
-	    t = p->var_value()->traverse_expression(traverse, traverse_mask);
-	  break;
-
-	case Named_object::NAMED_OBJECT_FUNC:
-	  if ((traverse_mask & Traverse::traverse_functions) != 0)
-	    t = traverse->function(p);
-
-	  if (t == TRAVERSE_CONTINUE
-	      && (traverse_mask
-		  & (Traverse::traverse_variables
-		     | Traverse::traverse_constants
-		     | Traverse::traverse_functions
-		     | Traverse::traverse_blocks
-		     | Traverse::traverse_statements
-		     | Traverse::traverse_expressions
-		     | Traverse::traverse_types)) != 0)
-	    t = p->func_value()->traverse(traverse);
-	  break;
-
-	case Named_object::NAMED_OBJECT_PACKAGE:
-	  // These are traversed in Gogo::traverse.
-	  go_assert(is_global);
-	  break;
-
-	case Named_object::NAMED_OBJECT_TYPE:
-	  if ((traverse_mask & e_or_t) != 0)
-	    t = Type::traverse(p->type_value(), traverse);
-	  break;
-
-	case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
-	case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
-	case Named_object::NAMED_OBJECT_UNKNOWN:
-	case Named_object::NAMED_OBJECT_ERRONEOUS:
-	  break;
-
-	case Named_object::NAMED_OBJECT_SINK:
-	default:
-	  go_unreachable();
-	}
-
-      if (t == TRAVERSE_EXIT)
+      if (p->traverse(traverse, is_global) == TRAVERSE_EXIT)
 	return TRAVERSE_EXIT;
     }
 
diff --git a/go/gogo.h b/go/gogo.h
index 9ffd120..2ee0fda 100644
--- a/go/gogo.h
+++ b/go/gogo.h
@@ -3047,6 +3047,10 @@
   Location
   location() const;
 
+  // Traverse a Named_object.
+  int
+  traverse(Traverse*, bool is_global);
+
   // Convert a variable to the backend representation.
   Bvariable*
   get_backend_variable(Gogo*, Named_object* function);