Go patch committed: Move Selector_expression up in file

Message ID CAOyqgcW0wZAzZJKOQZpVDesbprupOf47Vum=fTqWu9jvorzT2Q@mail.gmail.com
State Unresolved
Headers
Series Go patch committed: Move Selector_expression up in file |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Ian Lance Taylor Oct. 23, 2023, 9:16 p.m. UTC
  This patch to the Go frontend just moves Selector_expression up in
file.  This is a mechanical change to expressions.cc.  This will make
Selector_expression visible to Builtin_call_expression for later work.
This produces a very large "git --diff", but "git diff --minimal" is
clear.  Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.
Committed to mainline.

Ian
02aa322c8cfd3f60fa5a3a0eee4340bb644261fe
  

Patch

diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 35b9cd780da..aff74bd74dc 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@ 
-3c2a441ef6cafb018bb3cc16f8403ae3d1daf2e1
+e997b0201512110e9c20b1fdfd40014830031047
 
 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/expressions.cc b/gcc/go/gofrontend/expressions.cc
index f218731041b..c9177b71174 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -8426,6 +8426,287 @@  Expression::make_bound_method(Expression* expr, const Method* method,
   return new Bound_method_expression(expr, method, function, location);
 }
 
+// A general selector.  This is a Parser_expression for LEFT.NAME.  It
+// is lowered after we know the type of the left hand side.
+
+class Selector_expression : public Parser_expression
+{
+ public:
+  Selector_expression(Expression* left, const std::string& name,
+		      Location location)
+    : Parser_expression(EXPRESSION_SELECTOR, location),
+      left_(left), name_(name)
+  { }
+
+ protected:
+  int
+  do_traverse(Traverse* traverse)
+  { return Expression::traverse(&this->left_, traverse); }
+
+  Expression*
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
+
+  Expression*
+  do_copy()
+  {
+    return new Selector_expression(this->left_->copy(), this->name_,
+				   this->location());
+  }
+
+  void
+  do_dump_expression(Ast_dump_context* ast_dump_context) const;
+
+ private:
+  Expression*
+  lower_method_expression(Gogo*);
+
+  // The expression on the left hand side.
+  Expression* left_;
+  // The name on the right hand side.
+  std::string name_;
+};
+
+// Lower a selector expression once we know the real type of the left
+// hand side.
+
+Expression*
+Selector_expression::do_lower(Gogo* gogo, Named_object*, Statement_inserter*,
+			      int)
+{
+  Expression* left = this->left_;
+  if (left->is_type_expression())
+    return this->lower_method_expression(gogo);
+  return Type::bind_field_or_method(gogo, left->type(), left, this->name_,
+				    this->location());
+}
+
+// Lower a method expression T.M or (*T).M.  We turn this into a
+// function literal.
+
+Expression*
+Selector_expression::lower_method_expression(Gogo* gogo)
+{
+  Location location = this->location();
+  Type* left_type = this->left_->type();
+  Type* type = left_type;
+  const std::string& name(this->name_);
+
+  bool is_pointer;
+  if (type->points_to() == NULL)
+    is_pointer = false;
+  else
+    {
+      is_pointer = true;
+      type = type->points_to();
+    }
+
+  Named_type* nt = type->named_type();
+  Struct_type* st = type->struct_type();
+  bool is_ambiguous;
+  Method* method = NULL;
+  if (nt != NULL)
+    method = nt->method_function(name, &is_ambiguous);
+  else if (st != NULL)
+    method = st->method_function(name, &is_ambiguous);
+  const Typed_identifier* imethod = NULL;
+  if (method == NULL && !is_pointer)
+    {
+      Interface_type* it = type->interface_type();
+      if (it != NULL)
+	imethod = it->find_method(name);
+    }
+
+  if ((method == NULL && imethod == NULL)
+      || (left_type->named_type() != NULL && left_type->points_to() != NULL))
+    {
+      if (nt != NULL)
+	{
+	  if (!is_ambiguous)
+	    go_error_at(location, "type %<%s%s%> has no method %<%s%>",
+			is_pointer ? "*" : "",
+			nt->message_name().c_str(),
+			Gogo::message_name(name).c_str());
+	  else
+	    go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>",
+			Gogo::message_name(name).c_str(),
+			is_pointer ? "*" : "",
+			nt->message_name().c_str());
+	}
+      else
+	{
+	  if (!is_ambiguous)
+	    go_error_at(location, "type has no method %<%s%>",
+			Gogo::message_name(name).c_str());
+	  else
+	    go_error_at(location, "method %<%s%> is ambiguous",
+			Gogo::message_name(name).c_str());
+	}
+      return Expression::make_error(location);
+    }
+
+  if (method != NULL && !is_pointer && !method->is_value_method())
+    {
+      go_error_at(location, "method requires pointer (use %<(*%s).%s%>)",
+                  nt->message_name().c_str(),
+                  Gogo::message_name(name).c_str());
+      return Expression::make_error(location);
+    }
+
+  // Build a new function type in which the receiver becomes the first
+  // argument.
+  Function_type* method_type;
+  if (method != NULL)
+    {
+      method_type = method->type();
+      go_assert(method_type->is_method());
+    }
+  else
+    {
+      method_type = imethod->type()->function_type();
+      go_assert(method_type != NULL && !method_type->is_method());
+    }
+
+  const char* const receiver_name = "$this";
+  Typed_identifier_list* parameters = new Typed_identifier_list();
+  parameters->push_back(Typed_identifier(receiver_name, this->left_->type(),
+					 location));
+
+  const Typed_identifier_list* method_parameters = method_type->parameters();
+  if (method_parameters != NULL)
+    {
+      int i = 0;
+      for (Typed_identifier_list::const_iterator p = method_parameters->begin();
+	   p != method_parameters->end();
+	   ++p, ++i)
+	{
+	  if (!p->name().empty() && !Gogo::is_sink_name(p->name()))
+	    parameters->push_back(*p);
+	  else
+	    {
+	      char buf[20];
+	      snprintf(buf, sizeof buf, "$param%d", i);
+	      parameters->push_back(Typed_identifier(buf, p->type(),
+						     p->location()));
+	    }
+	}
+    }
+
+  const Typed_identifier_list* method_results = method_type->results();
+  Typed_identifier_list* results;
+  if (method_results == NULL)
+    results = NULL;
+  else
+    {
+      results = new Typed_identifier_list();
+      for (Typed_identifier_list::const_iterator p = method_results->begin();
+	   p != method_results->end();
+	   ++p)
+	results->push_back(*p);
+    }
+
+  Function_type* fntype = Type::make_function_type(NULL, parameters, results,
+						   location);
+  if (method_type->is_varargs())
+    fntype->set_is_varargs();
+
+  // We generate methods which always takes a pointer to the receiver
+  // as their first argument.  If this is for a pointer type, we can
+  // simply reuse the existing function.  We use an internal hack to
+  // get the right type.
+  // FIXME: This optimization is disabled because it doesn't yet work
+  // with function descriptors when the method expression is not
+  // directly called.
+  if (method != NULL && is_pointer && false)
+    {
+      Named_object* mno = (method->needs_stub_method()
+			   ? method->stub_object()
+			   : method->named_object());
+      Expression* f = Expression::make_func_reference(mno, NULL, location);
+      f = Expression::make_cast(fntype, f, location);
+      Type_conversion_expression* tce =
+	static_cast<Type_conversion_expression*>(f);
+      tce->set_may_convert_function_types();
+      return f;
+    }
+
+  Named_object* no = gogo->start_function(gogo->thunk_name(), fntype, false,
+					  location);
+
+  Named_object* vno = gogo->lookup(receiver_name, NULL);
+  go_assert(vno != NULL);
+  Expression* ve = Expression::make_var_reference(vno, location);
+  Expression* bm;
+  if (method != NULL)
+    bm = Type::bind_field_or_method(gogo, type, ve, name, location);
+  else
+    bm = Expression::make_interface_field_reference(ve, name, location);
+
+  // Even though we found the method above, if it has an error type we
+  // may see an error here.
+  if (bm->is_error_expression())
+    {
+      gogo->finish_function(location);
+      return bm;
+    }
+
+  Expression_list* args;
+  if (parameters->size() <= 1)
+    args = NULL;
+  else
+    {
+      args = new Expression_list();
+      Typed_identifier_list::const_iterator p = parameters->begin();
+      ++p;
+      for (; p != parameters->end(); ++p)
+	{
+	  vno = gogo->lookup(p->name(), NULL);
+	  go_assert(vno != NULL);
+	  args->push_back(Expression::make_var_reference(vno, location));
+	}
+    }
+
+  gogo->start_block(location);
+
+  Call_expression* call = Expression::make_call(bm, args,
+						method_type->is_varargs(),
+						location);
+
+  Statement* s = Statement::make_return_from_call(call, location);
+  gogo->add_statement(s);
+
+  Block* b = gogo->finish_block(location);
+
+  gogo->add_block(b, location);
+
+  // Lower the call in case there are multiple results.
+  gogo->lower_block(no, b);
+  gogo->flatten_block(no, b);
+
+  gogo->finish_function(location);
+
+  return Expression::make_func_reference(no, NULL, location);
+}
+
+// Dump the ast for a selector expression.
+
+void
+Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+    const
+{
+  ast_dump_context->dump_expression(this->left_);
+  ast_dump_context->ostream() << ".";
+  ast_dump_context->ostream() << this->name_;
+}
+
+// Make a selector expression.
+
+Expression*
+Expression::make_selector(Expression* left, const std::string& name,
+			  Location location)
+{
+  return new Selector_expression(left, name, location);
+}
+
 // Class Builtin_call_expression.  This is used for a call to a
 // builtin function.
 
@@ -15265,287 +15546,6 @@  Expression::make_interface_field_reference(Expression* expr,
   return new Interface_field_reference_expression(expr, field, location);
 }
 
-// A general selector.  This is a Parser_expression for LEFT.NAME.  It
-// is lowered after we know the type of the left hand side.
-
-class Selector_expression : public Parser_expression
-{
- public:
-  Selector_expression(Expression* left, const std::string& name,
-		      Location location)
-    : Parser_expression(EXPRESSION_SELECTOR, location),
-      left_(left), name_(name)
-  { }
-
- protected:
-  int
-  do_traverse(Traverse* traverse)
-  { return Expression::traverse(&this->left_, traverse); }
-
-  Expression*
-  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
-
-  Expression*
-  do_copy()
-  {
-    return new Selector_expression(this->left_->copy(), this->name_,
-				   this->location());
-  }
-
-  void
-  do_dump_expression(Ast_dump_context* ast_dump_context) const;
-
- private:
-  Expression*
-  lower_method_expression(Gogo*);
-
-  // The expression on the left hand side.
-  Expression* left_;
-  // The name on the right hand side.
-  std::string name_;
-};
-
-// Lower a selector expression once we know the real type of the left
-// hand side.
-
-Expression*
-Selector_expression::do_lower(Gogo* gogo, Named_object*, Statement_inserter*,
-			      int)
-{
-  Expression* left = this->left_;
-  if (left->is_type_expression())
-    return this->lower_method_expression(gogo);
-  return Type::bind_field_or_method(gogo, left->type(), left, this->name_,
-				    this->location());
-}
-
-// Lower a method expression T.M or (*T).M.  We turn this into a
-// function literal.
-
-Expression*
-Selector_expression::lower_method_expression(Gogo* gogo)
-{
-  Location location = this->location();
-  Type* left_type = this->left_->type();
-  Type* type = left_type;
-  const std::string& name(this->name_);
-
-  bool is_pointer;
-  if (type->points_to() == NULL)
-    is_pointer = false;
-  else
-    {
-      is_pointer = true;
-      type = type->points_to();
-    }
-
-  Named_type* nt = type->named_type();
-  Struct_type* st = type->struct_type();
-  bool is_ambiguous;
-  Method* method = NULL;
-  if (nt != NULL)
-    method = nt->method_function(name, &is_ambiguous);
-  else if (st != NULL)
-    method = st->method_function(name, &is_ambiguous);
-  const Typed_identifier* imethod = NULL;
-  if (method == NULL && !is_pointer)
-    {
-      Interface_type* it = type->interface_type();
-      if (it != NULL)
-	imethod = it->find_method(name);
-    }
-
-  if ((method == NULL && imethod == NULL)
-      || (left_type->named_type() != NULL && left_type->points_to() != NULL))
-    {
-      if (nt != NULL)
-	{
-	  if (!is_ambiguous)
-	    go_error_at(location, "type %<%s%s%> has no method %<%s%>",
-			is_pointer ? "*" : "",
-			nt->message_name().c_str(),
-			Gogo::message_name(name).c_str());
-	  else
-	    go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>",
-			Gogo::message_name(name).c_str(),
-			is_pointer ? "*" : "",
-			nt->message_name().c_str());
-	}
-      else
-	{
-	  if (!is_ambiguous)
-	    go_error_at(location, "type has no method %<%s%>",
-			Gogo::message_name(name).c_str());
-	  else
-	    go_error_at(location, "method %<%s%> is ambiguous",
-			Gogo::message_name(name).c_str());
-	}
-      return Expression::make_error(location);
-    }
-
-  if (method != NULL && !is_pointer && !method->is_value_method())
-    {
-      go_error_at(location, "method requires pointer (use %<(*%s).%s%>)",
-                  nt->message_name().c_str(),
-                  Gogo::message_name(name).c_str());
-      return Expression::make_error(location);
-    }
-
-  // Build a new function type in which the receiver becomes the first
-  // argument.
-  Function_type* method_type;
-  if (method != NULL)
-    {
-      method_type = method->type();
-      go_assert(method_type->is_method());
-    }
-  else
-    {
-      method_type = imethod->type()->function_type();
-      go_assert(method_type != NULL && !method_type->is_method());
-    }
-
-  const char* const receiver_name = "$this";
-  Typed_identifier_list* parameters = new Typed_identifier_list();
-  parameters->push_back(Typed_identifier(receiver_name, this->left_->type(),
-					 location));
-
-  const Typed_identifier_list* method_parameters = method_type->parameters();
-  if (method_parameters != NULL)
-    {
-      int i = 0;
-      for (Typed_identifier_list::const_iterator p = method_parameters->begin();
-	   p != method_parameters->end();
-	   ++p, ++i)
-	{
-	  if (!p->name().empty() && !Gogo::is_sink_name(p->name()))
-	    parameters->push_back(*p);
-	  else
-	    {
-	      char buf[20];
-	      snprintf(buf, sizeof buf, "$param%d", i);
-	      parameters->push_back(Typed_identifier(buf, p->type(),
-						     p->location()));
-	    }
-	}
-    }
-
-  const Typed_identifier_list* method_results = method_type->results();
-  Typed_identifier_list* results;
-  if (method_results == NULL)
-    results = NULL;
-  else
-    {
-      results = new Typed_identifier_list();
-      for (Typed_identifier_list::const_iterator p = method_results->begin();
-	   p != method_results->end();
-	   ++p)
-	results->push_back(*p);
-    }
-
-  Function_type* fntype = Type::make_function_type(NULL, parameters, results,
-						   location);
-  if (method_type->is_varargs())
-    fntype->set_is_varargs();
-
-  // We generate methods which always takes a pointer to the receiver
-  // as their first argument.  If this is for a pointer type, we can
-  // simply reuse the existing function.  We use an internal hack to
-  // get the right type.
-  // FIXME: This optimization is disabled because it doesn't yet work
-  // with function descriptors when the method expression is not
-  // directly called.
-  if (method != NULL && is_pointer && false)
-    {
-      Named_object* mno = (method->needs_stub_method()
-			   ? method->stub_object()
-			   : method->named_object());
-      Expression* f = Expression::make_func_reference(mno, NULL, location);
-      f = Expression::make_cast(fntype, f, location);
-      Type_conversion_expression* tce =
-	static_cast<Type_conversion_expression*>(f);
-      tce->set_may_convert_function_types();
-      return f;
-    }
-
-  Named_object* no = gogo->start_function(gogo->thunk_name(), fntype, false,
-					  location);
-
-  Named_object* vno = gogo->lookup(receiver_name, NULL);
-  go_assert(vno != NULL);
-  Expression* ve = Expression::make_var_reference(vno, location);
-  Expression* bm;
-  if (method != NULL)
-    bm = Type::bind_field_or_method(gogo, type, ve, name, location);
-  else
-    bm = Expression::make_interface_field_reference(ve, name, location);
-
-  // Even though we found the method above, if it has an error type we
-  // may see an error here.
-  if (bm->is_error_expression())
-    {
-      gogo->finish_function(location);
-      return bm;
-    }
-
-  Expression_list* args;
-  if (parameters->size() <= 1)
-    args = NULL;
-  else
-    {
-      args = new Expression_list();
-      Typed_identifier_list::const_iterator p = parameters->begin();
-      ++p;
-      for (; p != parameters->end(); ++p)
-	{
-	  vno = gogo->lookup(p->name(), NULL);
-	  go_assert(vno != NULL);
-	  args->push_back(Expression::make_var_reference(vno, location));
-	}
-    }
-
-  gogo->start_block(location);
-
-  Call_expression* call = Expression::make_call(bm, args,
-						method_type->is_varargs(),
-						location);
-
-  Statement* s = Statement::make_return_from_call(call, location);
-  gogo->add_statement(s);
-
-  Block* b = gogo->finish_block(location);
-
-  gogo->add_block(b, location);
-
-  // Lower the call in case there are multiple results.
-  gogo->lower_block(no, b);
-  gogo->flatten_block(no, b);
-
-  gogo->finish_function(location);
-
-  return Expression::make_func_reference(no, NULL, location);
-}
-
-// Dump the ast for a selector expression.
-
-void
-Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
-    const
-{
-  ast_dump_context->dump_expression(this->left_);
-  ast_dump_context->ostream() << ".";
-  ast_dump_context->ostream() << this->name_;
-}
-
-// Make a selector expression.
-
-Expression*
-Expression::make_selector(Expression* left, const std::string& name,
-			  Location location)
-{
-  return new Selector_expression(left, name, location);
-}
-
 // Class Allocation_expression.
 
 int