compiler: include selected constant types during export processing

The machinery that collects types referenced by expressions that are
part of inlinable function bodies was missing the types of local named
constants in certain cases. This patch updates the
Collect_export_references::expression() hook to look for references to
local named constants and include their types in the exported set.

Fixes golang/go#34577.

Change-Id: Ib80e7526c01edc1a3f2b422d84785ea67767c888
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/198017
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/go/export.cc b/go/export.cc
index 32ab498..5aaa207 100644
--- a/go/export.cc
+++ b/go/export.cc
@@ -249,6 +249,14 @@
       return TRAVERSE_CONTINUE;
     }
 
+  const Named_object* nco = expr->named_constant();
+  if (nco != 0 && nco->package() == NULL)
+    {
+      const Named_constant *nc = nco->const_value();
+      Type::traverse(nc->type(), this);
+      return TRAVERSE_CONTINUE;
+    }
+
   return TRAVERSE_CONTINUE;
 }
 
@@ -322,6 +330,10 @@
   if (type->is_void_type())
     return TRAVERSE_SKIP_COMPONENTS;
 
+  // Skip the nil type, turns up in function bodies.
+  if (type->is_nil_type())
+    return TRAVERSE_SKIP_COMPONENTS;
+
   // Skip abstract types.  We should never see these in real code,
   // only in things like const declarations.
   if (type->is_abstract())
diff --git a/go/expressions.cc b/go/expressions.cc
index 9babc34..b614921 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -3234,6 +3234,10 @@
   named_object()
   { return this->constant_; }
 
+  const Named_object*
+  named_object() const
+  { return this->constant_; }
+
   // Check that the initializer does not refer to the constant itself.
   void
   check_for_init_loop();
@@ -16782,6 +16786,15 @@
 	  || (no->is_variable() && !no->var_value()->is_global()));
 }
 
+const Named_object*
+Expression::named_constant() const
+{
+  if (this->classification() != EXPRESSION_CONST_REFERENCE)
+    return NULL;
+  const Const_expression* ce = static_cast<const Const_expression*>(this);
+  return ce->named_object();
+}
+
 // Class Type_guard_expression.
 
 // Traversal.
diff --git a/go/expressions.h b/go/expressions.h
index 2e3d1e0..a0370e1 100644
--- a/go/expressions.h
+++ b/go/expressions.h
@@ -587,6 +587,11 @@
   boolean_constant_value(bool* val) const
   { return this->do_boolean_constant_value(val); }
 
+  // If this is a const reference expression, return the named
+  // object to which the expression refers, otherwise return NULL.
+  const Named_object*
+  named_constant() const;
+
   // This is called if the value of this expression is being
   // discarded.  This issues warnings about computed values being
   // unused.  This returns true if all is well, false if it issued an