This patch to the Go frontend removes duplication of Named_object
traversal code.  Adding type parameters was about to add a partial
third version.  Remove the duplication to avoid that.  Bootstrapped
and ran Go testsuite on x86_64-pc-linux-gnu.  Committed to mainline.

Ian
5ef7d6c289350eb94ff6dd626b7d3f6c7ed65ea2
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 2d04f4b01c0..a18f3a37349 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-d3be41f0a1fca20e241e1db62b4b0f5262caac55
+9732b0766667b9235d0f35d0fb0abfe406b94d49
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 290d294e83b..e2fd509f58a 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -6890,80 +6890,12 @@ Block::traverse(Traverse* traverse)
          | 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 @@ Named_object::location() const
     }
 }
 
+// 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 @@ Bindings::traverse(Traverse* traverse, bool is_global)
   // 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/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 9ffd120290d..2ee0fda00ae 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -3047,6 +3047,10 @@ class Named_object
   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);

Reply via email to