// parse.cc -- Go frontend parser.

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "go-system.h"

#include "lex.h"
#include "gogo.h"
#include "go-diagnostics.h"
#include "types.h"
#include "statements.h"
#include "expressions.h"
#include "parse.h"

// Struct Parse::Enclosing_var_comparison.

// Return true if v1 should be considered to be less than v2.

bool
Parse::Enclosing_var_comparison::operator()(const Enclosing_var& v1,
					    const Enclosing_var& v2)
{
  if (v1.var() == v2.var())
    return false;

  const std::string& n1(v1.var()->name());
  const std::string& n2(v2.var()->name());
  int i = n1.compare(n2);
  if (i < 0)
    return true;
  else if (i > 0)
    return false;

  // If we get here it means that a single nested function refers to
  // two different variables defined in enclosing functions, and both
  // variables have the same name.  I think this is impossible.
  go_unreachable();
}

// Class Parse.

Parse::Parse(Lex* lex, Gogo* gogo)
  : lex_(lex),
    token_(Token::make_invalid_token(Linemap::unknown_location())),
    unget_token_(Token::make_invalid_token(Linemap::unknown_location())),
    unget_token_valid_(false),
    is_erroneous_function_(false),
    gogo_(gogo),
    break_stack_(NULL),
    continue_stack_(NULL),
    iota_(0),
    enclosing_vars_()
{
}

// Return the current token.

const Token*
Parse::peek_token()
{
  if (this->unget_token_valid_)
    return &this->unget_token_;
  if (this->token_.is_invalid())
    this->token_ = this->lex_->next_token();
  return &this->token_;
}

// Advance to the next token and return it.

const Token*
Parse::advance_token()
{
  if (this->unget_token_valid_)
    {
      this->unget_token_valid_ = false;
      if (!this->token_.is_invalid())
	return &this->token_;
    }
  this->token_ = this->lex_->next_token();
  return &this->token_;
}

// Push a token back on the input stream.

void
Parse::unget_token(const Token& token)
{
  go_assert(!this->unget_token_valid_);
  this->unget_token_ = token;
  this->unget_token_valid_ = true;
}

// The location of the current token.

Location
Parse::location()
{
  return this->peek_token()->location();
}

// IdentifierList = identifier { "," identifier } .

void
Parse::identifier_list(Typed_identifier_list* til)
{
  const Token* token = this->peek_token();
  while (true)
    {
      if (!token->is_identifier())
	{
	  go_error_at(this->location(), "expected identifier");
	  return;
	}
      std::string name =
	this->gogo_->pack_hidden_name(token->identifier(),
				      token->is_identifier_exported());
      til->push_back(Typed_identifier(name, NULL, token->location()));
      token = this->advance_token();
      if (!token->is_op(OPERATOR_COMMA))
	return;
      token = this->advance_token();
    }
}

// ExpressionList = Expression { "," Expression } .

// If MAY_BE_COMPOSITE_LIT is true, an expression may be a composite
// literal.

// If MAY_BE_SINK is true, the expressions in the list may be "_".

Expression_list*
Parse::expression_list(Expression* first, bool may_be_sink,
		       bool may_be_composite_lit)
{
  Expression_list* ret = new Expression_list();
  if (first != NULL)
    ret->push_back(first);
  while (true)
    {
      ret->push_back(this->expression(PRECEDENCE_NORMAL, may_be_sink,
				      may_be_composite_lit, NULL, NULL));

      const Token* token = this->peek_token();
      if (!token->is_op(OPERATOR_COMMA))
	return ret;

      // Most expression lists permit a trailing comma.
      Location location = token->location();
      this->advance_token();
      if (!this->expression_may_start_here())
	{
	  this->unget_token(Token::make_operator_token(OPERATOR_COMMA,
						       location));
	  return ret;
	}
    }
}

// QualifiedIdent = [ PackageName "." ] identifier .
// PackageName = identifier .

// This sets *PNAME to the identifier and sets *PPACKAGE to the
// package or NULL if there isn't one.  This returns true on success,
// false on failure in which case it will have emitted an error
// message.

bool
Parse::qualified_ident(std::string* pname, Named_object** ppackage)
{
  const Token* token = this->peek_token();
  if (!token->is_identifier())
    {
      go_error_at(this->location(), "expected identifier");
      return false;
    }

  std::string name = token->identifier();
  bool is_exported = token->is_identifier_exported();
  name = this->gogo_->pack_hidden_name(name, is_exported);

  token = this->advance_token();
  if (!token->is_op(OPERATOR_DOT))
    {
      *pname = name;
      *ppackage = NULL;
      return true;
    }

  Named_object* package = this->gogo_->lookup(name, NULL);
  if (package == NULL || !package->is_package())
    {
      go_error_at(this->location(), "expected package");
      // We expect . IDENTIFIER; skip both.
      if (this->advance_token()->is_identifier())
	this->advance_token();
      return false;
    }

  package->package_value()->note_usage(Gogo::unpack_hidden_name(name));

  token = this->advance_token();
  if (!token->is_identifier())
    {
      go_error_at(this->location(), "expected identifier");
      return false;
    }

  name = token->identifier();

  if (name == "_")
    {
      go_error_at(this->location(), "invalid use of %<_%>");
      name = Gogo::erroneous_name();
    }

  if (package->name() == this->gogo_->package_name())
    name = this->gogo_->pack_hidden_name(name,
					 token->is_identifier_exported());

  *pname = name;
  *ppackage = package;

  this->advance_token();

  return true;
}

// Type = TypeName | TypeLit | "(" Type ")" .
// TypeLit =
// 	ArrayType | StructType | PointerType | FunctionType | InterfaceType |
// 	SliceType | MapType | ChannelType .

Type*
Parse::type()
{
  const Token* token = this->peek_token();
  if (token->is_identifier())
    return this->type_name(true);
  else if (token->is_op(OPERATOR_LSQUARE))
    return this->array_type(false);
  else if (token->is_keyword(KEYWORD_CHAN)
	   || token->is_op(OPERATOR_CHANOP))
    return this->channel_type();
  else if (token->is_keyword(KEYWORD_INTERFACE))
    return this->interface_type(true);
  else if (token->is_keyword(KEYWORD_FUNC))
    {
      Location location = token->location();
      this->advance_token();
      Type* type = this->signature(NULL, location);
      if (type == NULL)
	return Type::make_error_type();
      return type;
    }
  else if (token->is_keyword(KEYWORD_MAP))
    return this->map_type();
  else if (token->is_keyword(KEYWORD_STRUCT))
    return this->struct_type();
  else if (token->is_op(OPERATOR_MULT))
    return this->pointer_type();
  else if (token->is_op(OPERATOR_LPAREN))
    {
      this->advance_token();
      Type* ret = this->type();
      if (this->peek_token()->is_op(OPERATOR_RPAREN))
	this->advance_token();
      else
	{
	  if (!ret->is_error_type())
	    go_error_at(this->location(), "expected %<)%>");
	}
      return ret;
    }
  else
    {
      go_error_at(token->location(), "expected type");
      return Type::make_error_type();
    }
}

bool
Parse::type_may_start_here()
{
  const Token* token = this->peek_token();
  return (token->is_identifier()
	  || token->is_op(OPERATOR_LSQUARE)
	  || token->is_op(OPERATOR_CHANOP)
	  || token->is_keyword(KEYWORD_CHAN)
	  || token->is_keyword(KEYWORD_INTERFACE)
	  || token->is_keyword(KEYWORD_FUNC)
	  || token->is_keyword(KEYWORD_MAP)
	  || token->is_keyword(KEYWORD_STRUCT)
	  || token->is_op(OPERATOR_MULT)
	  || token->is_op(OPERATOR_LPAREN));
}

// TypeName = QualifiedIdent .

// If MAY_BE_NIL is true, then an identifier with the value of the
// predefined constant nil is accepted, returning the nil type.

Type*
Parse::type_name(bool issue_error)
{
  Location location = this->location();

  std::string name;
  Named_object* package;
  if (!this->qualified_ident(&name, &package))
    return Type::make_error_type();

  Named_object* named_object;
  if (package == NULL)
    named_object = this->gogo_->lookup(name, NULL);
  else
    {
      named_object = package->package_value()->lookup(name);
      if (named_object == NULL
	  && issue_error
	  && package->name() != this->gogo_->package_name())
	{
	  // Check whether the name is there but hidden.
	  std::string s = ('.' + package->package_value()->pkgpath()
			   + '.' + name);
	  named_object = package->package_value()->lookup(s);
	  if (named_object != NULL)
	    {
	      Package* p = package->package_value();
	      const std::string& packname(p->package_name());
	      go_error_at(location,
			  "invalid reference to hidden type %<%s.%s%>",
			  Gogo::message_name(packname).c_str(),
			  Gogo::message_name(name).c_str());
	      issue_error = false;
	    }
	}
    }

  bool ok = true;
  if (named_object == NULL)
    {
      if (package == NULL)
	named_object = this->gogo_->add_unknown_name(name, location);
      else
	{
	  const std::string& packname(package->package_value()->package_name());
	  go_error_at(location, "reference to undefined identifier %<%s.%s%>",
		      Gogo::message_name(packname).c_str(),
		      Gogo::message_name(name).c_str());
	  issue_error = false;
	  ok = false;
	}
    }
  else if (named_object->is_type())
    {
      if (!named_object->type_value()->is_visible())
	ok = false;
    }
  else if (named_object->is_unknown() || named_object->is_type_declaration())
    ;
  else
    ok = false;

  if (!ok)
    {
      if (issue_error)
	go_error_at(location, "expected type");
      return Type::make_error_type();
    }

  if (named_object->is_type())
    return named_object->type_value();
  else if (named_object->is_unknown() || named_object->is_type_declaration())
    return Type::make_forward_declaration(named_object);
  else
    go_unreachable();
}

// ArrayType = "[" [ ArrayLength ] "]" ElementType .
// ArrayLength = Expression .
// ElementType = CompleteType .

Type*
Parse::array_type(bool may_use_ellipsis)
{
  go_assert(this->peek_token()->is_op(OPERATOR_LSQUARE));
  const Token* token = this->advance_token();

  Expression* length = NULL;
  if (token->is_op(OPERATOR_RSQUARE))
    this->advance_token();
  else
    {
      if (!token->is_op(OPERATOR_ELLIPSIS))
	length = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
      else if (may_use_ellipsis)
	{
	  // An ellipsis is used in composite literals to represent a
	  // fixed array of the size of the number of elements.  We
	  // use a length of nil to represent this, and change the
	  // length when parsing the composite literal.
	  length = Expression::make_nil(this->location());
	  this->advance_token();
	}
      else
	{
	  go_error_at(this->location(),
		      "use of %<[...]%> outside of array literal");
	  length = Expression::make_error(this->location());
	  this->advance_token();
	}
      if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
	{
	  go_error_at(this->location(), "expected %<]%>");
	  return Type::make_error_type();
	}
      this->advance_token();
    }

  Type* element_type = this->type();
  if (element_type->is_error_type())
    return Type::make_error_type();

  return Type::make_array_type(element_type, length);
}

// MapType = "map" "[" KeyType "]" ValueType .
// KeyType = CompleteType .
// ValueType = CompleteType .

Type*
Parse::map_type()
{
  Location location = this->location();
  go_assert(this->peek_token()->is_keyword(KEYWORD_MAP));
  if (!this->advance_token()->is_op(OPERATOR_LSQUARE))
    {
      go_error_at(this->location(), "expected %<[%>");
      return Type::make_error_type();
    }
  this->advance_token();

  Type* key_type = this->type();

  if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
    {
      go_error_at(this->location(), "expected %<]%>");
      return Type::make_error_type();
    }
  this->advance_token();

  Type* value_type = this->type();

  if (key_type->is_error_type() || value_type->is_error_type())
    return Type::make_error_type();

  return Type::make_map_type(key_type, value_type, location);
}

// StructType     = "struct" "{" { FieldDecl ";" } "}" .

Type*
Parse::struct_type()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_STRUCT));
  Location location = this->location();
  if (!this->advance_token()->is_op(OPERATOR_LCURLY))
    {
      Location token_loc = this->location();
      if (this->peek_token()->is_op(OPERATOR_SEMICOLON)
	  && this->advance_token()->is_op(OPERATOR_LCURLY))
	go_error_at(token_loc, "unexpected semicolon or newline before %<{%>");
      else
	{
	  go_error_at(this->location(), "expected %<{%>");
	  return Type::make_error_type();
	}
    }
  this->advance_token();

  Struct_field_list* sfl = new Struct_field_list;
  while (!this->peek_token()->is_op(OPERATOR_RCURLY))
    {
      this->field_decl(sfl);
      if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
	this->advance_token();
      else if (!this->peek_token()->is_op(OPERATOR_RCURLY))
	{
	  go_error_at(this->location(), "expected %<;%> or %<}%> or newline");
	  if (!this->skip_past_error(OPERATOR_RCURLY))
	    return Type::make_error_type();
	}
    }
  this->advance_token();

  for (Struct_field_list::const_iterator pi = sfl->begin();
       pi != sfl->end();
       ++pi)
    {
      if (pi->type()->is_error_type())
	return pi->type();
      for (Struct_field_list::const_iterator pj = pi + 1;
	   pj != sfl->end();
	   ++pj)
	{
	  if (pi->field_name() == pj->field_name()
	      && !Gogo::is_sink_name(pi->field_name()))
	    go_error_at(pi->location(), "duplicate field name %<%s%>",
			Gogo::message_name(pi->field_name()).c_str());
	}
    }

  return Type::make_struct_type(sfl, location);
}

// FieldDecl = (IdentifierList CompleteType | TypeName) [ Tag ] .
// Tag = string_lit .

void
Parse::field_decl(Struct_field_list* sfl)
{
  const Token* token = this->peek_token();
  Location location = token->location();
  bool is_anonymous;
  bool is_anonymous_pointer;
  if (token->is_op(OPERATOR_MULT))
    {
      is_anonymous = true;
      is_anonymous_pointer = true;
    }
  else if (token->is_identifier())
    {
      std::string id = token->identifier();
      bool is_id_exported = token->is_identifier_exported();
      Location id_location = token->location();
      token = this->advance_token();
      is_anonymous = (token->is_op(OPERATOR_SEMICOLON)
		      || token->is_op(OPERATOR_RCURLY)
		      || token->is_op(OPERATOR_DOT)
		      || token->is_string());
      is_anonymous_pointer = false;
      this->unget_token(Token::make_identifier_token(id, is_id_exported,
						     id_location));
    }
  else
    {
      go_error_at(this->location(), "expected field name");
      this->gogo_->mark_locals_used();
      while (!token->is_op(OPERATOR_SEMICOLON)
	     && !token->is_op(OPERATOR_RCURLY)
	     && !token->is_eof())
	token = this->advance_token();
      return;
    }

  if (is_anonymous)
    {
      if (is_anonymous_pointer)
	{
	  this->advance_token();
	  if (!this->peek_token()->is_identifier())
	    {
	      go_error_at(this->location(), "expected field name");
	      this->gogo_->mark_locals_used();
	      while (!token->is_op(OPERATOR_SEMICOLON)
		     && !token->is_op(OPERATOR_RCURLY)
		     && !token->is_eof())
		token = this->advance_token();
	      return;
	    }
	}
      Type* type = this->type_name(true);

      std::string tag;
      if (this->peek_token()->is_string())
	{
	  tag = this->peek_token()->string_value();
	  this->advance_token();
	}

      if (!type->is_error_type())
	{
	  if (is_anonymous_pointer)
	    type = Type::make_pointer_type(type);
	  sfl->push_back(Struct_field(Typed_identifier("", type, location)));
	  if (!tag.empty())
	    sfl->back().set_tag(tag);
	}
    }
  else
    {
      Typed_identifier_list til;
      while (true)
	{
	  token = this->peek_token();
	  if (!token->is_identifier())
	    {
	      go_error_at(this->location(), "expected identifier");
	      return;
	    }
	  std::string name =
	    this->gogo_->pack_hidden_name(token->identifier(),
					  token->is_identifier_exported());
	  til.push_back(Typed_identifier(name, NULL, token->location()));
	  if (!this->advance_token()->is_op(OPERATOR_COMMA))
	    break;
	  this->advance_token();
	}

      Type* type = this->type();

      std::string tag;
      if (this->peek_token()->is_string())
	{
	  tag = this->peek_token()->string_value();
	  this->advance_token();
	}

      for (Typed_identifier_list::iterator p = til.begin();
	   p != til.end();
	   ++p)
	{
	  p->set_type(type);
	  sfl->push_back(Struct_field(*p));
	  if (!tag.empty())
	    sfl->back().set_tag(tag);
	}
    }
}

// PointerType = "*" Type .

Type*
Parse::pointer_type()
{
  go_assert(this->peek_token()->is_op(OPERATOR_MULT));
  this->advance_token();
  Type* type = this->type();
  if (type->is_error_type())
    return type;
  return Type::make_pointer_type(type);
}

// ChannelType   = Channel | SendChannel | RecvChannel .
// Channel       = "chan" ElementType .
// SendChannel   = "chan" "<-" ElementType .
// RecvChannel   = "<-" "chan" ElementType .

Type*
Parse::channel_type()
{
  const Token* token = this->peek_token();
  bool send = true;
  bool receive = true;
  if (token->is_op(OPERATOR_CHANOP))
    {
      if (!this->advance_token()->is_keyword(KEYWORD_CHAN))
	{
	  go_error_at(this->location(), "expected %<chan%>");
	  return Type::make_error_type();
	}
      send = false;
      this->advance_token();
    }
  else
    {
      go_assert(token->is_keyword(KEYWORD_CHAN));
      if (this->advance_token()->is_op(OPERATOR_CHANOP))
	{
	  receive = false;
	  this->advance_token();
	}
    }

  // Better error messages for the common error of omitting the
  // channel element type.
  if (!this->type_may_start_here())
    {
      token = this->peek_token();
      if (token->is_op(OPERATOR_RCURLY))
	go_error_at(this->location(), "unexpected %<}%> in channel type");
      else if (token->is_op(OPERATOR_RPAREN))
	go_error_at(this->location(), "unexpected %<)%> in channel type");
      else if (token->is_op(OPERATOR_COMMA))
	go_error_at(this->location(), "unexpected comma in channel type");
      else
	go_error_at(this->location(), "expected channel element type");
      return Type::make_error_type();
    }

  Type* element_type = this->type();
  return Type::make_channel_type(send, receive, element_type);
}

// Give an error for a duplicate parameter or receiver name.

void
Parse::check_signature_names(const Typed_identifier_list* params,
			     Parse::Names* names)
{
  for (Typed_identifier_list::const_iterator p = params->begin();
       p != params->end();
       ++p)
    {
      if (p->name().empty() || Gogo::is_sink_name(p->name()))
	continue;
      std::pair<std::string, const Typed_identifier*> val =
	std::make_pair(p->name(), &*p);
      std::pair<Parse::Names::iterator, bool> ins = names->insert(val);
      if (!ins.second)
	{
	  go_error_at(p->location(), "redefinition of %qs",
		      Gogo::message_name(p->name()).c_str());
	  go_inform(ins.first->second->location(),
		    "previous definition of %qs was here",
		    Gogo::message_name(p->name()).c_str());
	}
    }
}

// Signature      = Parameters [ Result ] .

// RECEIVER is the receiver if there is one, or NULL.  LOCATION is the
// location of the start of the type.

// This returns NULL on a parse error.

Function_type*
Parse::signature(Typed_identifier* receiver, Location location)
{
  bool is_varargs = false;
  Typed_identifier_list* params;
  bool params_ok = this->parameters(&params, &is_varargs);

  Typed_identifier_list* results = NULL;
  if (this->peek_token()->is_op(OPERATOR_LPAREN)
      || this->type_may_start_here())
    {
      if (!this->result(&results))
	return NULL;
    }

  if (!params_ok)
    return NULL;

  Parse::Names names;
  if (receiver != NULL)
    names[receiver->name()] = receiver;
  if (params != NULL)
    this->check_signature_names(params, &names);
  if (results != NULL)
    this->check_signature_names(results, &names);

  Function_type* ret = Type::make_function_type(receiver, params, results,
						location);
  if (is_varargs)
    ret->set_is_varargs();
  return ret;
}

// Parameters     = "(" [ ParameterList [ "," ] ] ")" .

// This returns false on a parse error.

bool
Parse::parameters(Typed_identifier_list** pparams, bool* is_varargs)
{
  *pparams = NULL;

  if (!this->peek_token()->is_op(OPERATOR_LPAREN))
    {
      go_error_at(this->location(), "expected %<(%>");
      return false;
    }

  Typed_identifier_list* params = NULL;
  bool saw_error = false;

  const Token* token = this->advance_token();
  if (!token->is_op(OPERATOR_RPAREN))
    {
      params = this->parameter_list(is_varargs);
      if (params == NULL)
	saw_error = true;
      token = this->peek_token();
    }

  // The optional trailing comma is picked up in parameter_list.

  if (!token->is_op(OPERATOR_RPAREN))
    {
      go_error_at(this->location(), "expected %<)%>");
      return false;
    }
  this->advance_token();

  if (saw_error)
    return false;

  *pparams = params;
  return true;
}

// ParameterList  = ParameterDecl { "," ParameterDecl } .

// This sets *IS_VARARGS if the list ends with an ellipsis.
// IS_VARARGS will be NULL if varargs are not permitted.

// We pick up an optional trailing comma.

// This returns NULL if some error is seen.

Typed_identifier_list*
Parse::parameter_list(bool* is_varargs)
{
  Location location = this->location();
  Typed_identifier_list* ret = new Typed_identifier_list();

  bool saw_error = false;

  // If we see an identifier and then a comma, then we don't know
  // whether we are looking at a list of identifiers followed by a
  // type, or a list of types given by name.  We have to do an
  // arbitrary lookahead to figure it out.

  bool parameters_have_names;
  const Token* token = this->peek_token();
  if (!token->is_identifier())
    {
      // This must be a type which starts with something like '*'.
      parameters_have_names = false;
    }
  else
    {
      std::string name = token->identifier();
      bool is_exported = token->is_identifier_exported();
      Location location = token->location();
      token = this->advance_token();
      if (!token->is_op(OPERATOR_COMMA))
	{
	  if (token->is_op(OPERATOR_DOT))
	    {
	      // This is a qualified identifier, which must turn out
	      // to be a type.
	      parameters_have_names = false;
	    }
	  else if (token->is_op(OPERATOR_RPAREN))
	    {
	      // A single identifier followed by a parenthesis must be
	      // a type name.
	      parameters_have_names = false;
	    }
	  else
	    {
	      // An identifier followed by something other than a
	      // comma or a dot or a right parenthesis must be a
	      // parameter name followed by a type.
	      parameters_have_names = true;
	    }

	  this->unget_token(Token::make_identifier_token(name, is_exported,
							 location));
	}
      else
	{
	  // An identifier followed by a comma may be the first in a
	  // list of parameter names followed by a type, or it may be
	  // the first in a list of types without parameter names.  To
	  // find out we gather as many identifiers separated by
	  // commas as we can.
	  std::string id_name = this->gogo_->pack_hidden_name(name,
							      is_exported);
	  ret->push_back(Typed_identifier(id_name, NULL, location));
	  bool just_saw_comma = true;
	  while (this->advance_token()->is_identifier())
	    {
	      name = this->peek_token()->identifier();
	      is_exported = this->peek_token()->is_identifier_exported();
	      location = this->peek_token()->location();
	      id_name = this->gogo_->pack_hidden_name(name, is_exported);
	      ret->push_back(Typed_identifier(id_name, NULL, location));
	      if (!this->advance_token()->is_op(OPERATOR_COMMA))
		{
		  just_saw_comma = false;
		  break;
		}
	    }

	  if (just_saw_comma)
	    {
	      // We saw ID1 "," ID2 "," followed by something which
	      // was not an identifier.  We must be seeing the start
	      // of a type, and ID1 and ID2 must be types, and the
	      // parameters don't have names.
	      parameters_have_names = false;
	    }
	  else if (this->peek_token()->is_op(OPERATOR_RPAREN))
	    {
	      // We saw ID1 "," ID2 ")".  ID1 and ID2 must be types,
	      // and the parameters don't have names.
	      parameters_have_names = false;
	    }
	  else if (this->peek_token()->is_op(OPERATOR_DOT))
	    {
	      // We saw ID1 "," ID2 ".".  ID2 must be a package name,
	      // ID1 must be a type, and the parameters don't have
	      // names.
	      parameters_have_names = false;
	      this->unget_token(Token::make_identifier_token(name, is_exported,
							     location));
	      ret->pop_back();
	      just_saw_comma = true;
	    }
	  else
	    {
	      // We saw ID1 "," ID2 followed by something other than
	      // ",", ".", or ")".  We must be looking at the start of
	      // a type, and ID1 and ID2 must be parameter names.
	      parameters_have_names = true;
	    }

	  if (parameters_have_names)
	    {
	      go_assert(!just_saw_comma);
	      // We have just seen ID1, ID2 xxx.
	      Type* type;
	      if (!this->peek_token()->is_op(OPERATOR_ELLIPSIS))
		type = this->type();
	      else
		{
		  go_error_at(this->location(),
			      "%<...%> only permits one name");
		  saw_error = true;
		  this->advance_token();
		  type = this->type();
		}
	      for (size_t i = 0; i < ret->size(); ++i)
		ret->set_type(i, type);
	      if (!this->peek_token()->is_op(OPERATOR_COMMA))
		return saw_error ? NULL : ret;
	      if (this->advance_token()->is_op(OPERATOR_RPAREN))
		return saw_error ? NULL : ret;
	    }
	  else
	    {
	      Typed_identifier_list* tret = new Typed_identifier_list();
	      for (Typed_identifier_list::const_iterator p = ret->begin();
		   p != ret->end();
		   ++p)
		{
		  Named_object* no = this->gogo_->lookup(p->name(), NULL);
		  Type* type;
		  if (no == NULL)
		    no = this->gogo_->add_unknown_name(p->name(),
						       p->location());

		  if (no->is_type())
		    type = no->type_value();
		  else if (no->is_unknown() || no->is_type_declaration())
		    type = Type::make_forward_declaration(no);
		  else
		    {
		      go_error_at(p->location(), "expected %<%s%> to be a type",
				  Gogo::message_name(p->name()).c_str());
		      saw_error = true;
		      type = Type::make_error_type();
		    }
		  tret->push_back(Typed_identifier("", type, p->location()));
		}
	      delete ret;
	      ret = tret;
	      if (!just_saw_comma
		  || this->peek_token()->is_op(OPERATOR_RPAREN))
		return saw_error ? NULL : ret;
	    }
	}
    }

  bool mix_error = false;
  this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error,
		       &saw_error);
  while (this->peek_token()->is_op(OPERATOR_COMMA))
    {
      if (this->advance_token()->is_op(OPERATOR_RPAREN))
	break;
      if (is_varargs != NULL && *is_varargs)
	{
	  go_error_at(this->location(), "%<...%> must be last parameter");
	  saw_error = true;
	}
      this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error,
			   &saw_error);
    }
  if (mix_error)
    {
      go_error_at(location, "invalid named/anonymous mix");
      saw_error = true;
    }
  if (saw_error)
    {
      delete ret;
      return NULL;
    }
  return ret;
}

// ParameterDecl  = [ IdentifierList ] [ "..." ] Type .

void
Parse::parameter_decl(bool parameters_have_names,
		      Typed_identifier_list* til,
		      bool* is_varargs,
		      bool* mix_error,
		      bool* saw_error)
{
  if (!parameters_have_names)
    {
      Type* type;
      Location location = this->location();
      if (!this->peek_token()->is_identifier())
	{
	  if (!this->peek_token()->is_op(OPERATOR_ELLIPSIS))
	    type = this->type();
	  else
	    {
	      if (is_varargs == NULL)
		go_error_at(this->location(), "invalid use of %<...%>");
	      else
		*is_varargs = true;
	      this->advance_token();
	      if (is_varargs == NULL
		  && this->peek_token()->is_op(OPERATOR_RPAREN))
		type = Type::make_error_type();
	      else
		{
		  Type* element_type = this->type();
		  type = Type::make_array_type(element_type, NULL);
		}
	    }
	}
      else
	{
	  type = this->type_name(false);
	  if (type->is_error_type()
	      || (!this->peek_token()->is_op(OPERATOR_COMMA)
		  && !this->peek_token()->is_op(OPERATOR_RPAREN)))
	    {
	      *mix_error = true;
	      while (!this->peek_token()->is_op(OPERATOR_COMMA)
		     && !this->peek_token()->is_op(OPERATOR_RPAREN)
                     && !this->peek_token()->is_eof())
		this->advance_token();
	    }
	}
      if (!type->is_error_type())
	til->push_back(Typed_identifier("", type, location));
      else
	*saw_error = true;
    }
  else
    {
      size_t orig_count = til->size();
      if (this->peek_token()->is_identifier())
	this->identifier_list(til);
      else
	*mix_error = true;
      size_t new_count = til->size();

      Type* type;
      if (!this->peek_token()->is_op(OPERATOR_ELLIPSIS))
	type = this->type();
      else
	{
	  if (is_varargs == NULL)
	    {
	      go_error_at(this->location(), "invalid use of %<...%>");
	      *saw_error = true;
	    }
	  else if (new_count > orig_count + 1)
	    {
	      go_error_at(this->location(), "%<...%> only permits one name");
	      *saw_error = true;
	    }
	  else
	    *is_varargs = true;
	  this->advance_token();
	  Type* element_type = this->type();
	  type = Type::make_array_type(element_type, NULL);
	}
      for (size_t i = orig_count; i < new_count; ++i)
	til->set_type(i, type);
    }
}

// Result         = Parameters | Type .

// This returns false on a parse error.

bool
Parse::result(Typed_identifier_list** presults)
{
  if (this->peek_token()->is_op(OPERATOR_LPAREN))
    return this->parameters(presults, NULL);
  else
    {
      Location location = this->location();
      Type* type = this->type();
      if (type->is_error_type())
	{
	  *presults = NULL;
	  return false;
	}
      Typed_identifier_list* til = new Typed_identifier_list();
      til->push_back(Typed_identifier("", type, location));
      *presults = til;
      return true;
    }
}

// Block = "{" [ StatementList ] "}" .

// Returns the location of the closing brace.

Location
Parse::block()
{
  if (!this->peek_token()->is_op(OPERATOR_LCURLY))
    {
      Location loc = this->location();
      if (this->peek_token()->is_op(OPERATOR_SEMICOLON)
	  && this->advance_token()->is_op(OPERATOR_LCURLY))
	go_error_at(loc, "unexpected semicolon or newline before %<{%>");
      else
	{
	  go_error_at(this->location(), "expected %<{%>");
	  return Linemap::unknown_location();
	}
    }

  const Token* token = this->advance_token();

  if (!token->is_op(OPERATOR_RCURLY))
    {
      this->statement_list();
      token = this->peek_token();
      if (!token->is_op(OPERATOR_RCURLY))
	{
	  if (!token->is_eof() || !saw_errors())
	    go_error_at(this->location(), "expected %<}%>");

	  this->gogo_->mark_locals_used();

	  // Skip ahead to the end of the block, in hopes of avoiding
	  // lots of meaningless errors.
	  Location ret = token->location();
	  int nest = 0;
	  while (!token->is_eof())
	    {
	      if (token->is_op(OPERATOR_LCURLY))
		++nest;
	      else if (token->is_op(OPERATOR_RCURLY))
		{
		  --nest;
		  if (nest < 0)
		    {
		      this->advance_token();
		      break;
		    }
		}
	      token = this->advance_token();
	      ret = token->location();
	    }
	  return ret;
	}
    }

  Location ret = token->location();
  this->advance_token();
  return ret;
}

// InterfaceType      = "interface" "{" [ MethodSpecList ] "}" .
// MethodSpecList     = MethodSpec { ";" MethodSpec } [ ";" ] .

Type*
Parse::interface_type(bool record)
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_INTERFACE));
  Location location = this->location();

  if (!this->advance_token()->is_op(OPERATOR_LCURLY))
    {
      Location token_loc = this->location();
      if (this->peek_token()->is_op(OPERATOR_SEMICOLON)
	  && this->advance_token()->is_op(OPERATOR_LCURLY))
	go_error_at(token_loc, "unexpected semicolon or newline before %<{%>");
      else
	{
	  go_error_at(this->location(), "expected %<{%>");
	  return Type::make_error_type();
	}
    }
  this->advance_token();

  Typed_identifier_list* methods = new Typed_identifier_list();
  if (!this->peek_token()->is_op(OPERATOR_RCURLY))
    {
      this->method_spec(methods);
      while (this->peek_token()->is_op(OPERATOR_SEMICOLON))
	{
	  if (this->advance_token()->is_op(OPERATOR_RCURLY))
	    break;
	  this->method_spec(methods);
	}
      if (!this->peek_token()->is_op(OPERATOR_RCURLY))
	{
	  go_error_at(this->location(), "expected %<}%>");
	  while (!this->advance_token()->is_op(OPERATOR_RCURLY))
	    {
	      if (this->peek_token()->is_eof())
		return Type::make_error_type();
	    }
	}
    }
  this->advance_token();

  if (methods->empty())
    {
      delete methods;
      methods = NULL;
    }

  Interface_type* ret;
  if (methods == NULL)
    ret = Type::make_empty_interface_type(location);
  else
    ret = Type::make_interface_type(methods, location);
  if (record)
    this->gogo_->record_interface_type(ret);
  return ret;
}

// MethodSpec         = MethodName Signature | InterfaceTypeName .
// MethodName         = identifier .
// InterfaceTypeName  = TypeName .

void
Parse::method_spec(Typed_identifier_list* methods)
{
  const Token* token = this->peek_token();
  if (!token->is_identifier())
    {
      go_error_at(this->location(), "expected identifier");
      return;
    }

  std::string name = token->identifier();
  bool is_exported = token->is_identifier_exported();
  Location location = token->location();

  if (this->advance_token()->is_op(OPERATOR_LPAREN))
    {
      // This is a MethodName.
      if (name == "_")
	go_error_at(this->location(),
                    "methods must have a unique non-blank name");
      name = this->gogo_->pack_hidden_name(name, is_exported);
      Type* type = this->signature(NULL, location);
      if (type == NULL)
	return;
      methods->push_back(Typed_identifier(name, type, location));
    }
  else
    {
      this->unget_token(Token::make_identifier_token(name, is_exported,
						     location));
      Type* type = this->type_name(false);
      if (type->is_error_type()
	  || (!this->peek_token()->is_op(OPERATOR_SEMICOLON)
	      && !this->peek_token()->is_op(OPERATOR_RCURLY)))
	{
	  if (this->peek_token()->is_op(OPERATOR_COMMA))
	    go_error_at(this->location(),
			"name list not allowed in interface type");
	  else
	    go_error_at(location, "expected signature or type name");
	  this->gogo_->mark_locals_used();
	  token = this->peek_token();
	  while (!token->is_eof()
		 && !token->is_op(OPERATOR_SEMICOLON)
		 && !token->is_op(OPERATOR_RCURLY))
	    token = this->advance_token();
	  return;
	}
      // This must be an interface type, but we can't check that now.
      // We check it and pull out the methods in
      // Interface_type::do_verify.
      methods->push_back(Typed_identifier("", type, location));
    }
}

// Declaration = ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl .

void
Parse::declaration()
{
  const Token* token = this->peek_token();

  unsigned int pragmas = this->lex_->get_and_clear_pragmas();
  if (pragmas != 0 && !token->is_keyword(KEYWORD_FUNC))
    go_warning_at(token->location(), 0,
		  "ignoring magic comment before non-function");

  if (token->is_keyword(KEYWORD_CONST))
    this->const_decl();
  else if (token->is_keyword(KEYWORD_TYPE))
    this->type_decl();
  else if (token->is_keyword(KEYWORD_VAR))
    this->var_decl();
  else if (token->is_keyword(KEYWORD_FUNC))
    this->function_decl(pragmas);
  else
    {
      go_error_at(this->location(), "expected declaration");
      this->advance_token();
    }
}

bool
Parse::declaration_may_start_here()
{
  const Token* token = this->peek_token();
  return (token->is_keyword(KEYWORD_CONST)
	  || token->is_keyword(KEYWORD_TYPE)
	  || token->is_keyword(KEYWORD_VAR)
	  || token->is_keyword(KEYWORD_FUNC));
}

// Decl<P> = P | "(" [ List<P> ] ")" .

void
Parse::decl(void (Parse::*pfn)(void*), void* varg)
{
  if (this->peek_token()->is_eof())
    {
      if (!saw_errors())
	go_error_at(this->location(), "unexpected end of file");
      return;
    }

  if (!this->peek_token()->is_op(OPERATOR_LPAREN))
    (this->*pfn)(varg);
  else
    {
      if (!this->advance_token()->is_op(OPERATOR_RPAREN))
	{
	  this->list(pfn, varg, true);
	  if (!this->peek_token()->is_op(OPERATOR_RPAREN))
	    {
	      go_error_at(this->location(), "missing %<)%>");
	      while (!this->advance_token()->is_op(OPERATOR_RPAREN))
		{
		  if (this->peek_token()->is_eof())
		    return;
		}
	    }
	}
      this->advance_token();
    }
}

// List<P> = P { ";" P } [ ";" ] .

// In order to pick up the trailing semicolon we need to know what
// might follow.  This is either a '}' or a ')'.

void
Parse::list(void (Parse::*pfn)(void*), void* varg, bool follow_is_paren)
{
  (this->*pfn)(varg);
  Operator follow = follow_is_paren ? OPERATOR_RPAREN : OPERATOR_RCURLY;
  while (this->peek_token()->is_op(OPERATOR_SEMICOLON)
	 || this->peek_token()->is_op(OPERATOR_COMMA))
    {
      if (this->peek_token()->is_op(OPERATOR_COMMA))
	go_error_at(this->location(), "unexpected comma");
      if (this->advance_token()->is_op(follow))
	break;
      (this->*pfn)(varg);
    }
}

// ConstDecl      = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) .

void
Parse::const_decl()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_CONST));
  this->advance_token();
  this->reset_iota();

  Type* last_type = NULL;
  Expression_list* last_expr_list = NULL;

  if (!this->peek_token()->is_op(OPERATOR_LPAREN))
    this->const_spec(&last_type, &last_expr_list);
  else
    {
      this->advance_token();
      while (!this->peek_token()->is_op(OPERATOR_RPAREN))
	{
	  this->const_spec(&last_type, &last_expr_list);
	  if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
	    this->advance_token();
	  else if (!this->peek_token()->is_op(OPERATOR_RPAREN))
	    {
	      go_error_at(this->location(),
			  "expected %<;%> or %<)%> or newline");
	      if (!this->skip_past_error(OPERATOR_RPAREN))
		return;
	    }
	}
      this->advance_token();
    }

  if (last_expr_list != NULL)
    delete last_expr_list;
}

// ConstSpec = IdentifierList [ [ CompleteType ] "=" ExpressionList ] .

void
Parse::const_spec(Type** last_type, Expression_list** last_expr_list)
{
  Typed_identifier_list til;
  this->identifier_list(&til);

  Type* type = NULL;
  if (this->type_may_start_here())
    {
      type = this->type();
      *last_type = NULL;
      *last_expr_list = NULL;
    }

  Expression_list *expr_list;
  if (!this->peek_token()->is_op(OPERATOR_EQ))
    {
      if (*last_expr_list == NULL)
	{
	  go_error_at(this->location(), "expected %<=%>");
	  return;
	}
      type = *last_type;
      expr_list = new Expression_list;
      for (Expression_list::const_iterator p = (*last_expr_list)->begin();
	   p != (*last_expr_list)->end();
	   ++p)
	expr_list->push_back((*p)->copy());
    }
  else
    {
      this->advance_token();
      expr_list = this->expression_list(NULL, false, true);
      *last_type = type;
      if (*last_expr_list != NULL)
	delete *last_expr_list;
      *last_expr_list = expr_list;
    }

  Expression_list::const_iterator pe = expr_list->begin();
  for (Typed_identifier_list::iterator pi = til.begin();
       pi != til.end();
       ++pi, ++pe)
    {
      if (pe == expr_list->end())
	{
	  go_error_at(this->location(), "not enough initializers");
	  return;
	}
      if (type != NULL)
	pi->set_type(type);

      if (!Gogo::is_sink_name(pi->name()))
	this->gogo_->add_constant(*pi, *pe, this->iota_value());
      else
	{
	  static int count;
	  char buf[30];
	  snprintf(buf, sizeof buf, ".$sinkconst%d", count);
	  ++count;
	  Typed_identifier ti(std::string(buf), type, pi->location());
	  Named_object* no = this->gogo_->add_constant(ti, *pe, this->iota_value());
	  no->const_value()->set_is_sink();
	}
    }
  if (pe != expr_list->end())
    go_error_at(this->location(), "too many initializers");

  this->increment_iota();

  return;
}

// TypeDecl = "type" Decl<TypeSpec> .

void
Parse::type_decl()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_TYPE));
  this->advance_token();
  this->decl(&Parse::type_spec, NULL);
}

// TypeSpec = identifier ["="] Type .

void
Parse::type_spec(void*)
{
  const Token* token = this->peek_token();
  if (!token->is_identifier())
    {
      go_error_at(this->location(), "expected identifier");
      return;
    }
  std::string name = token->identifier();
  bool is_exported = token->is_identifier_exported();
  Location location = token->location();
  token = this->advance_token();

  bool is_alias = false;
  if (token->is_op(OPERATOR_EQ))
    {
      is_alias = true;
      token = this->advance_token();
    }

  // The scope of the type name starts at the point where the
  // identifier appears in the source code.  We implement this by
  // declaring the type before we read the type definition.
  Named_object* named_type = NULL;
  if (name != "_")
    {
      name = this->gogo_->pack_hidden_name(name, is_exported);
      named_type = this->gogo_->declare_type(name, location);
    }

  Type* type;
  if (name == "_" && token->is_keyword(KEYWORD_INTERFACE))
    {
      // We call Parse::interface_type explicity here because we do not want
      // to record an interface with a blank type name.
      type = this->interface_type(false);
    }
  else if (!token->is_op(OPERATOR_SEMICOLON))
    type = this->type();
  else
    {
      go_error_at(this->location(),
		  "unexpected semicolon or newline in type declaration");
      type = Type::make_error_type();
      this->advance_token();
    }

  if (type->is_error_type())
    {
      this->gogo_->mark_locals_used();
      while (!this->peek_token()->is_op(OPERATOR_SEMICOLON)
	     && !this->peek_token()->is_eof())
	this->advance_token();
    }

  if (name != "_")
    {
      if (named_type->is_type_declaration())
	{
	  Type* ftype = type->forwarded();
	  if (ftype->forward_declaration_type() != NULL
	      && (ftype->forward_declaration_type()->named_object()
		  == named_type))
	    {
	      go_error_at(location, "invalid recursive type");
	      type = Type::make_error_type();
	    }

	  Named_type* nt = Type::make_named_type(named_type, type, location);
	  if (is_alias)
	    nt->set_is_alias();

	  this->gogo_->define_type(named_type, nt);
	  go_assert(named_type->package() == NULL);
	}
      else
	{
	  // This will probably give a redefinition error.
	  this->gogo_->add_type(name, type, location);
	}
    }
}

// VarDecl = "var" Decl<VarSpec> .

void
Parse::var_decl()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_VAR));
  this->advance_token();
  this->decl(&Parse::var_spec, NULL);
}

// VarSpec = IdentifierList
//             ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) .

void
Parse::var_spec(void*)
{
  // Get the variable names.
  Typed_identifier_list til;
  this->identifier_list(&til);

  Location location = this->location();

  Type* type = NULL;
  Expression_list* init = NULL;
  if (!this->peek_token()->is_op(OPERATOR_EQ))
    {
      type = this->type();
      if (type->is_error_type())
	{
	  this->gogo_->mark_locals_used();
	  while (!this->peek_token()->is_op(OPERATOR_EQ)
		 && !this->peek_token()->is_op(OPERATOR_SEMICOLON)
		 && !this->peek_token()->is_eof())
	    this->advance_token();
	}
      if (this->peek_token()->is_op(OPERATOR_EQ))
	{
	  this->advance_token();
	  init = this->expression_list(NULL, false, true);
	}
    }
  else
    {
      this->advance_token();
      init = this->expression_list(NULL, false, true);
    }

  this->init_vars(&til, type, init, false, location);

  if (init != NULL)
    delete init;
}

// Create variables.  TIL is a list of variable names.  If TYPE is not
// NULL, it is the type of all the variables.  If INIT is not NULL, it
// is an initializer list for the variables.

void
Parse::init_vars(const Typed_identifier_list* til, Type* type,
		 Expression_list* init, bool is_coloneq,
		 Location location)
{
  // Check for an initialization which can yield multiple values.
  if (init != NULL && init->size() == 1 && til->size() > 1)
    {
      if (this->init_vars_from_call(til, type, *init->begin(), is_coloneq,
				    location))
	return;
      if (this->init_vars_from_map(til, type, *init->begin(), is_coloneq,
				   location))
	return;
      if (this->init_vars_from_receive(til, type, *init->begin(), is_coloneq,
				       location))
	return;
      if (this->init_vars_from_type_guard(til, type, *init->begin(),
					  is_coloneq, location))
	return;
    }

  if (init != NULL && init->size() != til->size())
    {
      if (init->empty() || !init->front()->is_error_expression())
	go_error_at(location, "wrong number of initializations");
      init = NULL;
      if (type == NULL)
	type = Type::make_error_type();
    }

  // Note that INIT was already parsed with the old name bindings, so
  // we don't have to worry that it will accidentally refer to the
  // newly declared variables.  But we do have to worry about a mix of
  // newly declared variables and old variables if the old variables
  // appear in the initializations.

  Expression_list::const_iterator pexpr;
  if (init != NULL)
    pexpr = init->begin();
  bool any_new = false;
  Expression_list* vars = new Expression_list();
  Expression_list* vals = new Expression_list();
  for (Typed_identifier_list::const_iterator p = til->begin();
       p != til->end();
       ++p)
    {
      if (init != NULL)
	go_assert(pexpr != init->end());
      this->init_var(*p, type, init == NULL ? NULL : *pexpr, is_coloneq,
		     false, &any_new, vars, vals);
      if (init != NULL)
	++pexpr;
    }
  if (init != NULL)
    go_assert(pexpr == init->end());
  if (is_coloneq && !any_new)
    go_error_at(location, "variables redeclared but no variable is new");
  this->finish_init_vars(vars, vals, location);
}

// See if we need to initialize a list of variables from a function
// call.  This returns true if we have set up the variables and the
// initialization.

bool
Parse::init_vars_from_call(const Typed_identifier_list* vars, Type* type,
			   Expression* expr, bool is_coloneq,
			   Location location)
{
  Call_expression* call = expr->call_expression();
  if (call == NULL)
    return false;

  // This is a function call.  We can't check here whether it returns
  // the right number of values, but it might.  Declare the variables,
  // and then assign the results of the call to them.

  call->set_expected_result_count(vars->size());

  Named_object* first_var = NULL;
  unsigned int index = 0;
  bool any_new = false;
  Expression_list* ivars = new Expression_list();
  Expression_list* ivals = new Expression_list();
  for (Typed_identifier_list::const_iterator pv = vars->begin();
       pv != vars->end();
       ++pv, ++index)
    {
      Expression* init = Expression::make_call_result(call, index);
      Named_object* no = this->init_var(*pv, type, init, is_coloneq, false,
					&any_new, ivars, ivals);

      if (this->gogo_->in_global_scope() && no->is_variable())
	{
	  if (first_var == NULL)
	    first_var = no;
	  else
	    {
              // If the current object is a redefinition of another object, we
              // might have already recorded the dependency relationship between
              // it and the first variable.  Either way, an error will be
              // reported for the redefinition and we don't need to properly
              // record dependency information for an invalid program.
              if (no->is_redefinition())
                continue;

	      // The subsequent vars have an implicit dependency on
	      // the first one, so that everything gets initialized in
	      // the right order and so that we detect cycles
	      // correctly.
	      this->gogo_->record_var_depends_on(no->var_value(), first_var);
	    }
	}
    }

  if (is_coloneq && !any_new)
    go_error_at(location, "variables redeclared but no variable is new");

  this->finish_init_vars(ivars, ivals, location);

  return true;
}

// See if we need to initialize a pair of values from a map index
// expression.  This returns true if we have set up the variables and
// the initialization.

bool
Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type,
			  Expression* expr, bool is_coloneq,
			  Location location)
{
  Index_expression* index = expr->index_expression();
  if (index == NULL)
    return false;
  if (vars->size() != 2)
    return false;

  // This is an index which is being assigned to two variables.  It
  // must be a map index.  Declare the variables, and then assign the
  // results of the map index.
  bool any_new = false;
  Typed_identifier_list::const_iterator p = vars->begin();
  Expression* init = type == NULL ? index : NULL;
  Named_object* val_no = this->init_var(*p, type, init, is_coloneq,
					type == NULL, &any_new, NULL, NULL);
  if (type == NULL && any_new && val_no->is_variable())
    val_no->var_value()->set_type_from_init_tuple();
  Expression* val_var = Expression::make_var_reference(val_no, location);

  ++p;
  Type* var_type = type;
  if (var_type == NULL)
    var_type = Type::lookup_bool_type();
  Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
				    &any_new, NULL, NULL);
  Expression* present_var = Expression::make_var_reference(no, location);

  if (is_coloneq && !any_new)
    go_error_at(location, "variables redeclared but no variable is new");

  Statement* s = Statement::make_tuple_map_assignment(val_var, present_var,
						      index, location);

  if (!this->gogo_->in_global_scope())
    this->gogo_->add_statement(s);
  else if (!val_no->is_sink())
    {
      if (val_no->is_variable())
	val_no->var_value()->add_preinit_statement(this->gogo_, s);
    }
  else if (!no->is_sink())
    {
      if (no->is_variable())
	no->var_value()->add_preinit_statement(this->gogo_, s);
    }
  else
    {
      // Execute the map index expression just so that we can fail if
      // the map is nil.
      Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(),
						      NULL, location);
      dummy->var_value()->add_preinit_statement(this->gogo_, s);
    }

  return true;
}

// See if we need to initialize a pair of values from a receive
// expression.  This returns true if we have set up the variables and
// the initialization.

bool
Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type,
			      Expression* expr, bool is_coloneq,
			      Location location)
{
  Receive_expression* receive = expr->receive_expression();
  if (receive == NULL)
    return false;
  if (vars->size() != 2)
    return false;

  // This is a receive expression which is being assigned to two
  // variables.  Declare the variables, and then assign the results of
  // the receive.
  bool any_new = false;
  Typed_identifier_list::const_iterator p = vars->begin();
  Expression* init = type == NULL ? receive : NULL;
  Named_object* val_no = this->init_var(*p, type, init, is_coloneq,
					type == NULL, &any_new, NULL, NULL);
  if (type == NULL && any_new && val_no->is_variable())
    val_no->var_value()->set_type_from_init_tuple();
  Expression* val_var = Expression::make_var_reference(val_no, location);

  ++p;
  Type* var_type = type;
  if (var_type == NULL)
    var_type = Type::lookup_bool_type();
  Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
				    &any_new, NULL, NULL);
  Expression* received_var = Expression::make_var_reference(no, location);

  if (is_coloneq && !any_new)
    go_error_at(location, "variables redeclared but no variable is new");

  Statement* s = Statement::make_tuple_receive_assignment(val_var,
							  received_var,
							  receive->channel(),
							  location);

  if (!this->gogo_->in_global_scope())
    this->gogo_->add_statement(s);
  else if (!val_no->is_sink())
    {
      if (val_no->is_variable())
	val_no->var_value()->add_preinit_statement(this->gogo_, s);
    }
  else if (!no->is_sink())
    {
      if (no->is_variable())
	no->var_value()->add_preinit_statement(this->gogo_, s);
    }
  else
    {
      Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(),
						      NULL, location);
      dummy->var_value()->add_preinit_statement(this->gogo_, s);
    }

  return true;
}

// See if we need to initialize a pair of values from a type guard
// expression.  This returns true if we have set up the variables and
// the initialization.

bool
Parse::init_vars_from_type_guard(const Typed_identifier_list* vars,
				 Type* type, Expression* expr,
				 bool is_coloneq, Location location)
{
  Type_guard_expression* type_guard = expr->type_guard_expression();
  if (type_guard == NULL)
    return false;
  if (vars->size() != 2)
    return false;

  // This is a type guard expression which is being assigned to two
  // variables.  Declare the variables, and then assign the results of
  // the type guard.
  bool any_new = false;
  Typed_identifier_list::const_iterator p = vars->begin();
  Type* var_type = type;
  if (var_type == NULL)
    var_type = type_guard->type();
  Named_object* val_no = this->init_var(*p, var_type, NULL, is_coloneq, false,
					&any_new, NULL, NULL);
  Expression* val_var = Expression::make_var_reference(val_no, location);

  ++p;
  var_type = type;
  if (var_type == NULL)
    var_type = Type::lookup_bool_type();
  Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
				    &any_new, NULL, NULL);
  Expression* ok_var = Expression::make_var_reference(no, location);

  Expression* texpr = type_guard->expr();
  Type* t = type_guard->type();
  Statement* s = Statement::make_tuple_type_guard_assignment(val_var, ok_var,
							     texpr, t,
							     location);

  if (is_coloneq && !any_new)
    go_error_at(location, "variables redeclared but no variable is new");

  if (!this->gogo_->in_global_scope())
    this->gogo_->add_statement(s);
  else if (!val_no->is_sink())
    {
      if (val_no->is_variable())
	val_no->var_value()->add_preinit_statement(this->gogo_, s);
    }
  else if (!no->is_sink())
    {
      if (no->is_variable())
	no->var_value()->add_preinit_statement(this->gogo_, s);
    }
  else
    {
      Named_object* dummy = this->create_dummy_global(type, NULL, location);
      dummy->var_value()->add_preinit_statement(this->gogo_, s);
    }

  return true;
}

// Create a single variable.  If IS_COLONEQ is true, we permit
// redeclarations in the same block, and we set *IS_NEW when we find a
// new variable which is not a redeclaration.

Named_object*
Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init,
		bool is_coloneq, bool type_from_init, bool* is_new,
		Expression_list* vars, Expression_list* vals)
{
  Location location = tid.location();

  if (Gogo::is_sink_name(tid.name()))
    {
      if (!type_from_init && init != NULL)
	{
	  if (this->gogo_->in_global_scope())
	    return this->create_dummy_global(type, init, location);
	  else
	    {
	      // Create a dummy variable so that we will check whether the
	      // initializer can be assigned to the type.
	      Variable* var = new Variable(type, init, false, false, false,
					   location);
	      var->set_is_used();
	      static int count;
	      char buf[30];
	      snprintf(buf, sizeof buf, "sink$%d", count);
	      ++count;
	      return this->gogo_->add_variable(buf, var);
	    }
	}
      if (type != NULL)
	this->gogo_->add_type_to_verify(type);
      return this->gogo_->add_sink();
    }

  if (is_coloneq)
    {
      Named_object* no = this->gogo_->lookup_in_block(tid.name());
      if (no != NULL
	  && (no->is_variable() || no->is_result_variable()))
	{
	  // INIT may be NULL even when IS_COLONEQ is true for cases
	  // like v, ok := x.(int).
	  if (!type_from_init && init != NULL)
	    {
	      go_assert(vars != NULL && vals != NULL);
	      vars->push_back(Expression::make_var_reference(no, location));
	      vals->push_back(init);
	    }
	  return no;
	}
    }
  *is_new = true;
  Variable* var = new Variable(type, init, this->gogo_->in_global_scope(),
			       false, false, location);
  Named_object* no = this->gogo_->add_variable(tid.name(), var);
  if (!no->is_variable())
    {
      // The name is already defined, so we just gave an error.
      return this->gogo_->add_sink();
    }
  return no;
}

// Create a dummy global variable to force an initializer to be run in
// the right place.  This is used when a sink variable is initialized
// at global scope.

Named_object*
Parse::create_dummy_global(Type* type, Expression* init,
			   Location location)
{
  if (type == NULL && init == NULL)
    type = Type::lookup_bool_type();
  Variable* var = new Variable(type, init, true, false, false, location);
  static int count;
  char buf[30];
  snprintf(buf, sizeof buf, "_.%d", count);
  ++count;
  return this->gogo_->add_variable(buf, var);
}

// Finish the variable initialization by executing any assignments to
// existing variables when using :=.  These must be done as a tuple
// assignment in case of something like n, a, b := 1, b, a.

void
Parse::finish_init_vars(Expression_list* vars, Expression_list* vals,
			Location location)
{
  if (vars->empty())
    {
      delete vars;
      delete vals;
    }
  else if (vars->size() == 1)
    {
      go_assert(!this->gogo_->in_global_scope());
      this->gogo_->add_statement(Statement::make_assignment(vars->front(),
							    vals->front(),
							    location));
      delete vars;
      delete vals;
    }
  else
    {
      go_assert(!this->gogo_->in_global_scope());
      this->gogo_->add_statement(Statement::make_tuple_assignment(vars, vals,
								  location));
    }
}

// SimpleVarDecl = identifier ":=" Expression .

// We've already seen the identifier.

// FIXME: We also have to implement
//  IdentifierList ":=" ExpressionList
// In order to support both "a, b := 1, 0" and "a, b = 1, 0" we accept
// tuple assignments here as well.

// If MAY_BE_COMPOSITE_LIT is true, the expression on the right hand
// side may be a composite literal.

// If P_RANGE_CLAUSE is not NULL, then this will recognize a
// RangeClause.

// If P_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").

void
Parse::simple_var_decl_or_assignment(const std::string& name,
				     Location location,
				     bool may_be_composite_lit,
				     Range_clause* p_range_clause,
				     Type_switch* p_type_switch)
{
  Typed_identifier_list til;
  til.push_back(Typed_identifier(name, NULL, location));

  std::set<std::string> uniq_idents;
  uniq_idents.insert(name);
  std::string dup_name;
  Location dup_loc;

  // We've seen one identifier.  If we see a comma now, this could be
  // "a, *p = 1, 2".
  if (this->peek_token()->is_op(OPERATOR_COMMA))
    {
      go_assert(p_type_switch == NULL);
      while (true)
	{
	  const Token* token = this->advance_token();
	  if (!token->is_identifier())
	    break;

	  std::string id = token->identifier();
	  bool is_id_exported = token->is_identifier_exported();
	  Location id_location = token->location();
	  std::pair<std::set<std::string>::iterator, bool> ins;

	  token = this->advance_token();
	  if (!token->is_op(OPERATOR_COMMA))
	    {
	      if (token->is_op(OPERATOR_COLONEQ))
		{
		  id = this->gogo_->pack_hidden_name(id, is_id_exported);
		  ins = uniq_idents.insert(id);
		  if (!ins.second && !Gogo::is_sink_name(id))
		    go_error_at(id_location, "multiple assignments to %s",
				Gogo::message_name(id).c_str());
		  til.push_back(Typed_identifier(id, NULL, location));
		}
	      else
		this->unget_token(Token::make_identifier_token(id,
							       is_id_exported,
							       id_location));
	      break;
	    }

	  id = this->gogo_->pack_hidden_name(id, is_id_exported);
	  ins = uniq_idents.insert(id);
	  if (!ins.second && !Gogo::is_sink_name(id))
	    {
	      dup_name = Gogo::message_name(id);
	      dup_loc = id_location;
	    }
	  til.push_back(Typed_identifier(id, NULL, location));
	}

      // We have a comma separated list of identifiers in TIL.  If the
      // next token is COLONEQ, then this is a simple var decl, and we
      // have the complete list of identifiers.  If the next token is
      // not COLONEQ, then the only valid parse is a tuple assignment.
      // The list of identifiers we have so far is really a list of
      // expressions.  There are more expressions following.

      if (!this->peek_token()->is_op(OPERATOR_COLONEQ))
	{
	  Expression_list* exprs = new Expression_list;
	  for (Typed_identifier_list::const_iterator p = til.begin();
	       p != til.end();
	       ++p)
	    exprs->push_back(this->id_to_expression(p->name(), p->location(),
						    true));

	  Expression_list* more_exprs =
	    this->expression_list(NULL, true, may_be_composite_lit);
	  for (Expression_list::const_iterator p = more_exprs->begin();
	       p != more_exprs->end();
	       ++p)
	    exprs->push_back(*p);
	  delete more_exprs;

	  this->tuple_assignment(exprs, may_be_composite_lit, p_range_clause);
	  return;
	}
    }

  go_assert(this->peek_token()->is_op(OPERATOR_COLONEQ));
  const Token* token = this->advance_token();

  if (!dup_name.empty())
    go_error_at(dup_loc, "multiple assignments to %s", dup_name.c_str());

  if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE))
    {
      this->range_clause_decl(&til, p_range_clause);
      return;
    }

  Expression_list* init;
  if (p_type_switch == NULL)
    init = this->expression_list(NULL, false, may_be_composite_lit);
  else
    {
      bool is_type_switch = false;
      Expression* expr = this->expression(PRECEDENCE_NORMAL, false,
					  may_be_composite_lit,
					  &is_type_switch, NULL);
      if (is_type_switch)
	{
	  p_type_switch->found = true;
	  p_type_switch->name = name;
	  p_type_switch->location = location;
	  p_type_switch->expr = expr;
	  return;
	}

      if (!this->peek_token()->is_op(OPERATOR_COMMA))
	{
	  init = new Expression_list();
	  init->push_back(expr);
	}
      else
	{
	  this->advance_token();
	  init = this->expression_list(expr, false, may_be_composite_lit);
	}
    }

  this->init_vars(&til, NULL, init, true, location);
}

// FunctionDecl = "func" identifier Signature [ Block ] .
// MethodDecl = "func" Receiver identifier Signature [ Block ] .

// Deprecated gcc extension:
//   FunctionDecl = "func" identifier Signature
//                    __asm__ "(" string_lit ")" .
// This extension means a function whose real name is the identifier
// inside the asm.  This extension will be removed at some future
// date.  It has been replaced with //extern or //go:linkname comments.
//
// PRAGMAS is a bitset of magic comments.

void
Parse::function_decl(unsigned int pragmas)
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_FUNC));
  Location location = this->location();
  std::string extern_name = this->lex_->extern_name();
  const Token* token = this->advance_token();

  bool expected_receiver = false;
  Typed_identifier* rec = NULL;
  if (token->is_op(OPERATOR_LPAREN))
    {
      expected_receiver = true;
      rec = this->receiver();
      token = this->peek_token();
    }

  if (!token->is_identifier())
    {
      go_error_at(this->location(), "expected function name");
      return;
    }

  std::string name =
    this->gogo_->pack_hidden_name(token->identifier(),
				  token->is_identifier_exported());

  this->advance_token();

  Function_type* fntype = this->signature(rec, this->location());

  Named_object* named_object = NULL;

  if (this->peek_token()->is_keyword(KEYWORD_ASM))
    {
      if (!this->advance_token()->is_op(OPERATOR_LPAREN))
	{
	  go_error_at(this->location(), "expected %<(%>");
	  return;
	}
      token = this->advance_token();
      if (!token->is_string())
	{
	  go_error_at(this->location(), "expected string");
	  return;
	}
      std::string asm_name = token->string_value();
      if (!this->advance_token()->is_op(OPERATOR_RPAREN))
	{
	  go_error_at(this->location(), "expected %<)%>");
	  return;
	}
      this->advance_token();
      if (!Gogo::is_sink_name(name))
	{
	  named_object = this->gogo_->declare_function(name, fntype, location);
	  if (named_object->is_function_declaration())
	    named_object->func_declaration_value()->set_asm_name(asm_name);
	}
    }

  // Check for the easy error of a newline before the opening brace.
  if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
    {
      Location semi_loc = this->location();
      if (this->advance_token()->is_op(OPERATOR_LCURLY))
	go_error_at(this->location(),
		    "unexpected semicolon or newline before %<{%>");
      else
	this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON,
						     semi_loc));
    }

  static struct {
    unsigned int bit;
    const char* name;
    bool decl_ok;
    bool func_ok;
    bool method_ok;
  } pragma_check[] =
      {
	{ GOPRAGMA_NOINTERFACE, "nointerface", false, false, true },
	{ GOPRAGMA_NOESCAPE, "noescape", true, false, false },
	{ GOPRAGMA_NORACE, "norace", false, true, true },
	{ GOPRAGMA_NOSPLIT, "nosplit", false, true, true },
	{ GOPRAGMA_NOINLINE, "noinline", false, true, true },
	{ GOPRAGMA_SYSTEMSTACK, "systemstack", false, true, true },
	{ GOPRAGMA_NOWRITEBARRIER, "nowritebarrier", false, true, true },
	{ GOPRAGMA_NOWRITEBARRIERREC, "nowritebarrierrec", false, true, true },
	{ GOPRAGMA_CGOUNSAFEARGS, "cgo_unsafe_args", false, true, true },
	{ GOPRAGMA_UINTPTRESCAPES, "uintptrescapes", true, true, true },
      };

  bool is_decl = !this->peek_token()->is_op(OPERATOR_LCURLY);
  if (pragmas != 0)
    {
      for (size_t i = 0;
	   i < sizeof(pragma_check) / sizeof(pragma_check[0]);
	   ++i)
	{
	  if ((pragmas & pragma_check[i].bit) == 0)
	    continue;

	  if (is_decl)
	    {
	      if (pragma_check[i].decl_ok)
		continue;
	      go_warning_at(location, 0,
			    ("ignoring magic //go:%s comment "
			     "before declaration"),
			    pragma_check[i].name);
	    }
	  else if (rec == NULL)
	    {
	      if (pragma_check[i].func_ok)
		continue;
	      go_warning_at(location, 0,
			    ("ignoring magic //go:%s comment "
			     "before function definition"),
			    pragma_check[i].name);
	    }
	  else
	    {
	      if (pragma_check[i].method_ok)
		continue;
	      go_warning_at(location, 0,
			    ("ignoring magic //go:%s comment "
			     "before method definition"),
			    pragma_check[i].name);
	    }

	  pragmas &= ~ pragma_check[i].bit;
	}
    }

  if (is_decl)
    {
      if (named_object == NULL)
	{
          // Function declarations with the blank identifier as a name are
          // mostly ignored since they cannot be called.  We make an object
          // for this declaration for type-checking purposes.
          if (Gogo::is_sink_name(name))
            {
              static int count;
              char buf[30];
              snprintf(buf, sizeof buf, ".$sinkfndecl%d", count);
              ++count;
              name = std::string(buf);
            }

	  if (fntype == NULL
              || (expected_receiver && rec == NULL))
	    this->gogo_->add_erroneous_name(name);
	  else
	    {
	      named_object = this->gogo_->declare_function(name, fntype,
							   location);
	      if (!extern_name.empty()
		  && named_object->is_function_declaration())
		{
		  Function_declaration* fd =
		    named_object->func_declaration_value();
		  fd->set_asm_name(extern_name);
		}
	    }
	}

      if (pragmas != 0 && named_object->is_function_declaration())
	named_object->func_declaration_value()->set_pragmas(pragmas);
    }
  else
    {
      bool hold_is_erroneous_function = this->is_erroneous_function_;
      if (fntype == NULL)
	{
	  fntype = Type::make_function_type(NULL, NULL, NULL, location);
	  this->is_erroneous_function_ = true;
	  if (!Gogo::is_sink_name(name))
	    this->gogo_->add_erroneous_name(name);
	  name = this->gogo_->pack_hidden_name("_", false);
	}
      named_object = this->gogo_->start_function(name, fntype, true, location);
      Location end_loc = this->block();
      this->gogo_->finish_function(end_loc);

      if (pragmas != 0
	  && !this->is_erroneous_function_
	  && named_object->is_function())
	named_object->func_value()->set_pragmas(pragmas);
      this->is_erroneous_function_ = hold_is_erroneous_function;
    }
}

// Receiver = Parameters .

Typed_identifier*
Parse::receiver()
{
  Location location = this->location();
  Typed_identifier_list* til;
  if (!this->parameters(&til, NULL))
    return NULL;
  else if (til == NULL || til->empty())
    {
      go_error_at(location, "method has no receiver");
      return NULL;
    }
  else if (til->size() > 1)
    {
      go_error_at(location, "method has multiple receivers");
      return NULL;
    }
  else
    return &til->front();
}

// Operand    = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
// Literal    = BasicLit | CompositeLit | FunctionLit .
// BasicLit   = int_lit | float_lit | imaginary_lit | char_lit | string_lit .

// If MAY_BE_SINK is true, this operand may be "_".

// If IS_PARENTHESIZED is not NULL, *IS_PARENTHESIZED is set to true
// if the entire expression is in parentheses.

Expression*
Parse::operand(bool may_be_sink, bool* is_parenthesized)
{
  const Token* token = this->peek_token();
  Expression* ret;
  switch (token->classification())
    {
    case Token::TOKEN_IDENTIFIER:
      {
	Location location = token->location();
	std::string id = token->identifier();
	bool is_exported = token->is_identifier_exported();
	std::string packed = this->gogo_->pack_hidden_name(id, is_exported);

	Named_object* in_function;
	Named_object* named_object = this->gogo_->lookup(packed, &in_function);

	Package* package = NULL;
	if (named_object != NULL && named_object->is_package())
	  {
	    if (!this->advance_token()->is_op(OPERATOR_DOT)
		|| !this->advance_token()->is_identifier())
	      {
		go_error_at(location, "unexpected reference to package");
		return Expression::make_error(location);
	      }
	    package = named_object->package_value();
	    package->note_usage(id);
	    id = this->peek_token()->identifier();
	    is_exported = this->peek_token()->is_identifier_exported();
	    packed = this->gogo_->pack_hidden_name(id, is_exported);
	    named_object = package->lookup(packed);
	    location = this->location();
	    go_assert(in_function == NULL);
	  }

	this->advance_token();

	if (named_object != NULL
	    && named_object->is_type()
	    && !named_object->type_value()->is_visible())
	  {
	    go_assert(package != NULL);
	    go_error_at(location, "invalid reference to hidden type %<%s.%s%>",
			Gogo::message_name(package->package_name()).c_str(),
			Gogo::message_name(id).c_str());
	    return Expression::make_error(location);
	  }


	if (named_object == NULL)
	  {
	    if (package != NULL)
	      {
		std::string n1 = Gogo::message_name(package->package_name());
		std::string n2 = Gogo::message_name(id);
		if (!is_exported)
		  go_error_at(location,
			      ("invalid reference to unexported identifier "
			       "%<%s.%s%>"),
			      n1.c_str(), n2.c_str());
		else
		  go_error_at(location,
			      "reference to undefined identifier %<%s.%s%>",
			      n1.c_str(), n2.c_str());
		return Expression::make_error(location);
	      }

	    named_object = this->gogo_->add_unknown_name(packed, location);
	  }

	if (in_function != NULL
	    && in_function != this->gogo_->current_function()
	    && (named_object->is_variable()
		|| named_object->is_result_variable()))
	  return this->enclosing_var_reference(in_function, named_object,
					       may_be_sink, location);

	switch (named_object->classification())
	  {
	  case Named_object::NAMED_OBJECT_CONST:
	    return Expression::make_const_reference(named_object, location);
	  case Named_object::NAMED_OBJECT_TYPE:
	    return Expression::make_type(named_object->type_value(), location);
	  case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
	    {
	      Type* t = Type::make_forward_declaration(named_object);
	      return Expression::make_type(t, location);
	    }
	  case Named_object::NAMED_OBJECT_VAR:
	  case Named_object::NAMED_OBJECT_RESULT_VAR:
	    // Any left-hand-side can be a sink, so if this can not be
	    // a sink, then it must be a use of the variable.
	    if (!may_be_sink)
	      this->mark_var_used(named_object);
	    return Expression::make_var_reference(named_object, location);
	  case Named_object::NAMED_OBJECT_SINK:
	    if (may_be_sink)
	      return Expression::make_sink(location);
	    else
	      {
		go_error_at(location, "cannot use _ as value");
		return Expression::make_error(location);
	      }
	  case Named_object::NAMED_OBJECT_FUNC:
	  case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
	    return Expression::make_func_reference(named_object, NULL,
						   location);
	  case Named_object::NAMED_OBJECT_UNKNOWN:
	    {
	      Unknown_expression* ue =
		Expression::make_unknown_reference(named_object, location);
	      if (this->is_erroneous_function_)
		ue->set_no_error_message();
	      return ue;
	    }
	  case Named_object::NAMED_OBJECT_ERRONEOUS:
	    return Expression::make_error(location);
	  default:
	    go_unreachable();
	  }
      }
      go_unreachable();

    case Token::TOKEN_STRING:
      ret = Expression::make_string(token->string_value(), token->location());
      this->advance_token();
      return ret;

    case Token::TOKEN_CHARACTER:
      ret = Expression::make_character(token->character_value(), NULL,
				       token->location());
      this->advance_token();
      return ret;

    case Token::TOKEN_INTEGER:
      ret = Expression::make_integer_z(token->integer_value(), NULL,
				       token->location());
      this->advance_token();
      return ret;

    case Token::TOKEN_FLOAT:
      ret = Expression::make_float(token->float_value(), NULL,
				   token->location());
      this->advance_token();
      return ret;

    case Token::TOKEN_IMAGINARY:
      {
	mpfr_t zero;
	mpfr_init_set_ui(zero, 0, GMP_RNDN);
	mpc_t val;
	mpc_init2(val, mpc_precision);
	mpc_set_fr_fr(val, zero, *token->imaginary_value(), MPC_RNDNN);
	mpfr_clear(zero);
	ret = Expression::make_complex(&val, NULL, token->location());
	mpc_clear(val);
	this->advance_token();
	return ret;
      }

    case Token::TOKEN_KEYWORD:
      switch (token->keyword())
	{
	case KEYWORD_FUNC:
	  return this->function_lit();
	case KEYWORD_CHAN:
	case KEYWORD_INTERFACE:
	case KEYWORD_MAP:
	case KEYWORD_STRUCT:
	  {
	    Location location = token->location();
	    return Expression::make_type(this->type(), location);
	  }
	default:
	  break;
	}
      break;

    case Token::TOKEN_OPERATOR:
      if (token->is_op(OPERATOR_LPAREN))
	{
	  this->advance_token();
	  ret = this->expression(PRECEDENCE_NORMAL, may_be_sink, true, NULL,
				 NULL);
	  if (!this->peek_token()->is_op(OPERATOR_RPAREN))
	    go_error_at(this->location(), "missing %<)%>");
	  else
	    this->advance_token();
	  if (is_parenthesized != NULL)
	    *is_parenthesized = true;
	  return ret;
	}
      else if (token->is_op(OPERATOR_LSQUARE))
	{
	  // Here we call array_type directly, as this is the only
	  // case where an ellipsis is permitted for an array type.
	  Location location = token->location();
	  return Expression::make_type(this->array_type(true), location);
	}
      break;

    default:
      break;
    }

  go_error_at(this->location(), "expected operand");
  return Expression::make_error(this->location());
}

// Handle a reference to a variable in an enclosing function.  We add
// it to a list of such variables.  We return a reference to a field
// in a struct which will be passed on the static chain when calling
// the current function.

Expression*
Parse::enclosing_var_reference(Named_object* in_function, Named_object* var,
			       bool may_be_sink, Location location)
{
  go_assert(var->is_variable() || var->is_result_variable());

  // Any left-hand-side can be a sink, so if this can not be
  // a sink, then it must be a use of the variable.
  if (!may_be_sink)
    this->mark_var_used(var);

  Named_object* this_function = this->gogo_->current_function();
  Named_object* closure = this_function->func_value()->closure_var();

  // The last argument to the Enclosing_var constructor is the index
  // of this variable in the closure.  We add 1 to the current number
  // of enclosed variables, because the first field in the closure
  // points to the function code.
  Enclosing_var ev(var, in_function, this->enclosing_vars_.size() + 1);
  std::pair<Enclosing_vars::iterator, bool> ins =
    this->enclosing_vars_.insert(ev);
  if (ins.second)
    {
      // This is a variable we have not seen before.  Add a new field
      // to the closure type.
      this_function->func_value()->add_closure_field(var, location);
    }

  Expression* closure_ref = Expression::make_var_reference(closure,
							   location);
  closure_ref = Expression::make_unary(OPERATOR_MULT, closure_ref, location);

  // The closure structure holds pointers to the variables, so we need
  // to introduce an indirection.
  Expression* e = Expression::make_field_reference(closure_ref,
						   ins.first->index(),
						   location);
  e = Expression::make_unary(OPERATOR_MULT, e, location);
  return Expression::make_enclosing_var_reference(e, var, location);
}

// CompositeLit  = LiteralType LiteralValue .
// LiteralType   = StructType | ArrayType | "[" "..." "]" ElementType |
//                 SliceType | MapType | TypeName .
// LiteralValue  = "{" [ ElementList [ "," ] ] "}" .
// ElementList   = Element { "," Element } .
// Element       = [ Key ":" ] Value .
// Key           = FieldName | ElementIndex .
// FieldName     = identifier .
// ElementIndex  = Expression .
// Value         = Expression | LiteralValue .

// We have already seen the type if there is one, and we are now
// looking at the LiteralValue.  The case "[" "..."  "]" ElementType
// will be seen here as an array type whose length is "nil".  The
// DEPTH parameter is non-zero if this is an embedded composite
// literal and the type was omitted.  It gives the number of steps up
// to the type which was provided.  E.g., in [][]int{{1}} it will be
// 1.  In [][][]int{{{1}}} it will be 2.

Expression*
Parse::composite_lit(Type* type, int depth, Location location)
{
  go_assert(this->peek_token()->is_op(OPERATOR_LCURLY));
  this->advance_token();

  if (this->peek_token()->is_op(OPERATOR_RCURLY))
    {
      this->advance_token();
      return Expression::make_composite_literal(type, depth, false, NULL,
						false, location);
    }

  bool has_keys = false;
  bool all_are_names = true;
  Expression_list* vals = new Expression_list;
  while (true)
    {
      Expression* val;
      bool is_type_omitted = false;
      bool is_name = false;

      const Token* token = this->peek_token();

      if (token->is_identifier())
	{
	  std::string identifier = token->identifier();
	  bool is_exported = token->is_identifier_exported();
	  Location location = token->location();

	  if (this->advance_token()->is_op(OPERATOR_COLON))
	    {
	      // This may be a field name.  We don't know for sure--it
	      // could also be an expression for an array index.  We
	      // don't want to parse it as an expression because may
	      // trigger various errors, e.g., if this identifier
	      // happens to be the name of a package.
	      Gogo* gogo = this->gogo_;
	      val = this->id_to_expression(gogo->pack_hidden_name(identifier,
								  is_exported),
					   location, false);
	      is_name = true;
	    }
	  else
	    {
	      this->unget_token(Token::make_identifier_token(identifier,
							     is_exported,
							     location));
	      val = this->expression(PRECEDENCE_NORMAL, false, true, NULL,
				     NULL);
	    }
	}
      else if (!token->is_op(OPERATOR_LCURLY))
	val = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
      else
	{
	  // This must be a composite literal inside another composite
	  // literal, with the type omitted for the inner one.
	  val = this->composite_lit(type, depth + 1, token->location());
          is_type_omitted = true;
	}

      token = this->peek_token();
      if (!token->is_op(OPERATOR_COLON))
	{
	  if (has_keys)
	    vals->push_back(NULL);
	  is_name = false;
	}
      else
	{
          if (is_type_omitted)
            {
              // VAL is a nested composite literal with an omitted type being
              // used a key.  Record this information in VAL so that the correct
              // type is associated with the literal value if VAL is a
              // map literal.
              val->complit()->update_key_path(depth);
            }

	  this->advance_token();

	  if (!has_keys && !vals->empty())
	    {
	      Expression_list* newvals = new Expression_list;
	      for (Expression_list::const_iterator p = vals->begin();
		   p != vals->end();
		   ++p)
		{
		  newvals->push_back(NULL);
		  newvals->push_back(*p);
		}
	      delete vals;
	      vals = newvals;
	    }
	  has_keys = true;

	  if (val->unknown_expression() != NULL)
	    val->unknown_expression()->set_is_composite_literal_key();

	  vals->push_back(val);

	  if (!token->is_op(OPERATOR_LCURLY))
	    val = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
	  else
	    {
	      // This must be a composite literal inside another
	      // composite literal, with the type omitted for the
	      // inner one.
	      val = this->composite_lit(type, depth + 1, token->location());
	    }

	  token = this->peek_token();
	}

      vals->push_back(val);

      if (!is_name)
	all_are_names = false;

      if (token->is_op(OPERATOR_COMMA))
	{
	  if (this->advance_token()->is_op(OPERATOR_RCURLY))
	    {
	      this->advance_token();
	      break;
	    }
	}
      else if (token->is_op(OPERATOR_RCURLY))
	{
	  this->advance_token();
	  break;
	}
      else
	{
	  if (token->is_op(OPERATOR_SEMICOLON))
	    go_error_at(this->location(),
			("need trailing comma before newline "
			 "in composite literal"));
	  else
	    go_error_at(this->location(), "expected %<,%> or %<}%>");

	  this->gogo_->mark_locals_used();
	  int depth = 0;
	  while (!token->is_eof()
		 && (depth > 0 || !token->is_op(OPERATOR_RCURLY)))
	    {
	      if (token->is_op(OPERATOR_LCURLY))
		++depth;
	      else if (token->is_op(OPERATOR_RCURLY))
		--depth;
	      token = this->advance_token();
	    }
	  if (token->is_op(OPERATOR_RCURLY))
	    this->advance_token();

	  return Expression::make_error(location);
	}
    }

  return Expression::make_composite_literal(type, depth, has_keys, vals,
					    all_are_names, location);
}

// FunctionLit = "func" Signature Block .

Expression*
Parse::function_lit()
{
  Location location = this->location();
  go_assert(this->peek_token()->is_keyword(KEYWORD_FUNC));
  this->advance_token();

  Enclosing_vars hold_enclosing_vars;
  hold_enclosing_vars.swap(this->enclosing_vars_);

  Function_type* type = this->signature(NULL, location);
  bool fntype_is_error = false;
  if (type == NULL)
    {
      type = Type::make_function_type(NULL, NULL, NULL, location);
      fntype_is_error = true;
    }

  // For a function literal, the next token must be a '{'.  If we
  // don't see that, then we may have a type expression.
  if (!this->peek_token()->is_op(OPERATOR_LCURLY))
    {
      hold_enclosing_vars.swap(this->enclosing_vars_);
      return Expression::make_type(type, location);
    }

  bool hold_is_erroneous_function = this->is_erroneous_function_;
  if (fntype_is_error)
    this->is_erroneous_function_ = true;

  Bc_stack* hold_break_stack = this->break_stack_;
  Bc_stack* hold_continue_stack = this->continue_stack_;
  this->break_stack_ = NULL;
  this->continue_stack_ = NULL;

  Named_object* no = this->gogo_->start_function("", type, true, location);

  Location end_loc = this->block();

  this->gogo_->finish_function(end_loc);

  if (this->break_stack_ != NULL)
    delete this->break_stack_;
  if (this->continue_stack_ != NULL)
    delete this->continue_stack_;
  this->break_stack_ = hold_break_stack;
  this->continue_stack_ = hold_continue_stack;

  this->is_erroneous_function_ = hold_is_erroneous_function;

  hold_enclosing_vars.swap(this->enclosing_vars_);

  Expression* closure = this->create_closure(no, &hold_enclosing_vars,
					     location);

  return Expression::make_func_reference(no, closure, location);
}

// Create a closure for the nested function FUNCTION.  This is based
// on ENCLOSING_VARS, which is a list of all variables defined in
// enclosing functions and referenced from FUNCTION.  A closure is the
// address of a struct which point to the real function code and
// contains the addresses of all the referenced variables.  This
// returns NULL if no closure is required.

Expression*
Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars,
		      Location location)
{
  if (enclosing_vars->empty())
    return NULL;

  // Get the variables in order by their field index.

  size_t enclosing_var_count = enclosing_vars->size();
  std::vector<Enclosing_var> ev(enclosing_var_count);
  for (Enclosing_vars::const_iterator p = enclosing_vars->begin();
       p != enclosing_vars->end();
       ++p)
    {
      // Subtract 1 because index 0 is the function code.
      ev[p->index() - 1] = *p;
    }

  // Build an initializer for a composite literal of the closure's
  // type.

  Named_object* enclosing_function = this->gogo_->current_function();
  Expression_list* initializer = new Expression_list;

  initializer->push_back(Expression::make_func_code_reference(function,
							      location));

  for (size_t i = 0; i < enclosing_var_count; ++i)
    {
      // Add 1 to i because the first field in the closure is a
      // pointer to the function code.
      go_assert(ev[i].index() == i + 1);
      Named_object* var = ev[i].var();
      Expression* ref;
      if (ev[i].in_function() == enclosing_function)
	ref = Expression::make_var_reference(var, location);
      else
	ref = this->enclosing_var_reference(ev[i].in_function(), var,
					    true, location);
      Expression* refaddr = Expression::make_unary(OPERATOR_AND, ref,
						   location);
      initializer->push_back(refaddr);
    }

  Named_object* closure_var = function->func_value()->closure_var();
  Struct_type* st = closure_var->var_value()->type()->deref()->struct_type();
  Expression* cv = Expression::make_struct_composite_literal(st, initializer,
							     location);

  // When compiling the runtime, closures do not escape.  When escape
  // analysis becomes the default, and applies to closures, this
  // should be changed to make it an error if a closure escapes.
  if (this->gogo_->compiling_runtime()
      && this->gogo_->package_name() == "runtime")
    {
      Temporary_statement* ctemp = Statement::make_temporary(st, cv, location);
      this->gogo_->add_statement(ctemp);
      Expression* ref = Expression::make_temporary_reference(ctemp, location);
      Expression* addr = Expression::make_unary(OPERATOR_AND, ref, location);
      addr->unary_expression()->set_does_not_escape();
      return addr;
    }

  return Expression::make_heap_expression(cv, location);
}

// PrimaryExpr = Operand { Selector | Index | Slice | TypeGuard | Call } .

// If MAY_BE_SINK is true, this expression may be "_".

// If MAY_BE_COMPOSITE_LIT is true, this expression may be a composite
// literal.

// If IS_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").

// If IS_PARENTHESIZED is not NULL, *IS_PARENTHESIZED is set to true
// if the entire expression is in parentheses.

Expression*
Parse::primary_expr(bool may_be_sink, bool may_be_composite_lit,
		    bool* is_type_switch, bool* is_parenthesized)
{
  Location start_loc = this->location();
  bool operand_is_parenthesized = false;
  bool whole_is_parenthesized = false;

  Expression* ret = this->operand(may_be_sink, &operand_is_parenthesized);

  whole_is_parenthesized = operand_is_parenthesized;

  // An unknown name followed by a curly brace must be a composite
  // literal, and the unknown name must be a type.
  if (may_be_composite_lit
      && !operand_is_parenthesized
      && ret->unknown_expression() != NULL
      && this->peek_token()->is_op(OPERATOR_LCURLY))
    {
      Named_object* no = ret->unknown_expression()->named_object();
      Type* type = Type::make_forward_declaration(no);
      ret = Expression::make_type(type, ret->location());
    }

  // We handle composite literals and type casts here, as it is the
  // easiest way to handle types which are in parentheses, as in
  // "((uint))(1)".
  if (ret->is_type_expression())
    {
      if (this->peek_token()->is_op(OPERATOR_LCURLY))
	{
	  whole_is_parenthesized = false;
	  if (!may_be_composite_lit)
	    {
	      Type* t = ret->type();
	      if (t->named_type() != NULL
		  || t->forward_declaration_type() != NULL)
		go_error_at(start_loc,
			    _("parentheses required around this composite "
			      "literal to avoid parsing ambiguity"));
	    }
	  else if (operand_is_parenthesized)
	    go_error_at(start_loc,
			"cannot parenthesize type in composite literal");
	  ret = this->composite_lit(ret->type(), 0, ret->location());
	}
      else if (this->peek_token()->is_op(OPERATOR_LPAREN))
	{
	  whole_is_parenthesized = false;
	  Location loc = this->location();
	  this->advance_token();
	  Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true,
					      NULL, NULL);
	  if (this->peek_token()->is_op(OPERATOR_COMMA))
	    this->advance_token();
	  if (this->peek_token()->is_op(OPERATOR_ELLIPSIS))
	    {
	      go_error_at(this->location(),
			  "invalid use of %<...%> in type conversion");
	      this->advance_token();
	    }
	  if (!this->peek_token()->is_op(OPERATOR_RPAREN))
	    go_error_at(this->location(), "expected %<)%>");
	  else
	    this->advance_token();
	  if (expr->is_error_expression())
	    ret = expr;
	  else
	    {
	      Type* t = ret->type();
	      if (t->classification() == Type::TYPE_ARRAY
		  && t->array_type()->length() != NULL
		  && t->array_type()->length()->is_nil_expression())
		{
		  go_error_at(ret->location(),
			      "use of %<[...]%> outside of array literal");
		  ret = Expression::make_error(loc);
		}
	      else
		ret = Expression::make_cast(t, expr, loc);
	    }
	}
    }

  while (true)
    {
      const Token* token = this->peek_token();
      if (token->is_op(OPERATOR_LPAREN))
	{
	  whole_is_parenthesized = false;
	  ret = this->call(this->verify_not_sink(ret));
	}
      else if (token->is_op(OPERATOR_DOT))
	{
	  whole_is_parenthesized = false;
	  ret = this->selector(this->verify_not_sink(ret), is_type_switch);
	  if (is_type_switch != NULL && *is_type_switch)
	    break;
	}
      else if (token->is_op(OPERATOR_LSQUARE))
	{
	  whole_is_parenthesized = false;
	  ret = this->index(this->verify_not_sink(ret));
	}
      else
	break;
    }

  if (whole_is_parenthesized && is_parenthesized != NULL)
    *is_parenthesized = true;

  return ret;
}

// Selector = "." identifier .
// TypeGuard = "." "(" QualifiedIdent ")" .

// Note that Operand can expand to QualifiedIdent, which contains a
// ".".  That is handled directly in operand when it sees a package
// name.

// If IS_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").

Expression*
Parse::selector(Expression* left, bool* is_type_switch)
{
  go_assert(this->peek_token()->is_op(OPERATOR_DOT));
  Location location = this->location();

  const Token* token = this->advance_token();
  if (token->is_identifier())
    {
      // This could be a field in a struct, or a method in an
      // interface, or a method associated with a type.  We can't know
      // which until we have seen all the types.
      std::string name =
	this->gogo_->pack_hidden_name(token->identifier(),
				      token->is_identifier_exported());
      if (token->identifier() == "_")
	{
	  go_error_at(this->location(), "invalid use of %<_%>");
	  name = Gogo::erroneous_name();
	}
      this->advance_token();
      return Expression::make_selector(left, name, location);
    }
  else if (token->is_op(OPERATOR_LPAREN))
    {
      this->advance_token();
      Type* type = NULL;
      if (!this->peek_token()->is_keyword(KEYWORD_TYPE))
	type = this->type();
      else
	{
	  if (is_type_switch != NULL)
	    *is_type_switch = true;
	  else
	    {
	      go_error_at(this->location(),
			  "use of %<.(type)%> outside type switch");
	      type = Type::make_error_type();
	    }
	  this->advance_token();
	}
      if (!this->peek_token()->is_op(OPERATOR_RPAREN))
	go_error_at(this->location(), "missing %<)%>");
      else
	this->advance_token();
      if (is_type_switch != NULL && *is_type_switch)
	return left;
      return Expression::make_type_guard(left, type, location);
    }
  else
    {
      go_error_at(this->location(), "expected identifier or %<(%>");
      return left;
    }
}

// Index          = "[" Expression "]" .
// Slice          = "[" Expression ":" [ Expression ] [ ":" Expression ] "]" .

Expression*
Parse::index(Expression* expr)
{
  Location location = this->location();
  go_assert(this->peek_token()->is_op(OPERATOR_LSQUARE));
  this->advance_token();

  Expression* start;
  if (!this->peek_token()->is_op(OPERATOR_COLON))
    start = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
  else
    start = Expression::make_integer_ul(0, NULL, location);

  Expression* end = NULL;
  if (this->peek_token()->is_op(OPERATOR_COLON))
    {
      // We use nil to indicate a missing high expression.
      if (this->advance_token()->is_op(OPERATOR_RSQUARE))
	end = Expression::make_nil(this->location());
      else if (this->peek_token()->is_op(OPERATOR_COLON))
	{
	  go_error_at(this->location(),
		      "middle index required in 3-index slice");
	  end = Expression::make_error(this->location());
	}
      else
	end = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
    }

  Expression* cap = NULL;
  if (this->peek_token()->is_op(OPERATOR_COLON))
    {
      if (this->advance_token()->is_op(OPERATOR_RSQUARE))
	{
	  go_error_at(this->location(),
		      "final index required in 3-index slice");
	  cap = Expression::make_error(this->location());
	}
      else
        cap = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
    }
  if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
    go_error_at(this->location(), "missing %<]%>");
  else
    this->advance_token();
  return Expression::make_index(expr, start, end, cap, location);
}

// Call           = "(" [ ArgumentList [ "," ] ] ")" .
// ArgumentList   = ExpressionList [ "..." ] .

Expression*
Parse::call(Expression* func)
{
  go_assert(this->peek_token()->is_op(OPERATOR_LPAREN));
  Expression_list* args = NULL;
  bool is_varargs = false;
  const Token* token = this->advance_token();
  if (!token->is_op(OPERATOR_RPAREN))
    {
      args = this->expression_list(NULL, false, true);
      token = this->peek_token();
      if (token->is_op(OPERATOR_ELLIPSIS))
	{
	  is_varargs = true;
	  token = this->advance_token();
	}
    }
  if (token->is_op(OPERATOR_COMMA))
    token = this->advance_token();
  if (!token->is_op(OPERATOR_RPAREN))
    {
      go_error_at(this->location(), "missing %<)%>");
      if (!this->skip_past_error(OPERATOR_RPAREN))
	return Expression::make_error(this->location());
    }
  this->advance_token();
  if (func->is_error_expression())
    return func;
  return Expression::make_call(func, args, is_varargs, func->location());
}

// Return an expression for a single unqualified identifier.

Expression*
Parse::id_to_expression(const std::string& name, Location location,
			bool is_lhs)
{
  Named_object* in_function;
  Named_object* named_object = this->gogo_->lookup(name, &in_function);
  if (named_object == NULL)
    named_object = this->gogo_->add_unknown_name(name, location);

  if (in_function != NULL
      && in_function != this->gogo_->current_function()
      && (named_object->is_variable() || named_object->is_result_variable()))
    return this->enclosing_var_reference(in_function, named_object, is_lhs,
					 location);

  switch (named_object->classification())
    {
    case Named_object::NAMED_OBJECT_CONST:
      return Expression::make_const_reference(named_object, location);
    case Named_object::NAMED_OBJECT_VAR:
    case Named_object::NAMED_OBJECT_RESULT_VAR:
      if (!is_lhs)
	this->mark_var_used(named_object);
      return Expression::make_var_reference(named_object, location);
    case Named_object::NAMED_OBJECT_SINK:
      return Expression::make_sink(location);
    case Named_object::NAMED_OBJECT_FUNC:
    case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
      return Expression::make_func_reference(named_object, NULL, location);
    case Named_object::NAMED_OBJECT_UNKNOWN:
      {
	Unknown_expression* ue =
	  Expression::make_unknown_reference(named_object, location);
	if (this->is_erroneous_function_)
	  ue->set_no_error_message();
	return ue;
      }
    case Named_object::NAMED_OBJECT_PACKAGE:
    case Named_object::NAMED_OBJECT_TYPE:
    case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
      {
	// These cases can arise for a field name in a composite
	// literal.  Keep track of these as they might be fake uses of
	// the related package.
	Unknown_expression* ue =
	  Expression::make_unknown_reference(named_object, location);
	if (named_object->package() != NULL)
	  named_object->package()->note_fake_usage(ue);
	if (this->is_erroneous_function_)
	  ue->set_no_error_message();
	return ue;
      }
    case Named_object::NAMED_OBJECT_ERRONEOUS:
      return Expression::make_error(location);
    default:
      go_error_at(this->location(), "unexpected type of identifier");
      return Expression::make_error(location);
    }
}

// Expression = UnaryExpr { binary_op Expression } .

// PRECEDENCE is the precedence of the current operator.

// If MAY_BE_SINK is true, this expression may be "_".

// If MAY_BE_COMPOSITE_LIT is true, this expression may be a composite
// literal.

// If IS_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").

// If IS_PARENTHESIZED is not NULL, *IS_PARENTHESIZED is set to true
// if the entire expression is in parentheses.

Expression*
Parse::expression(Precedence precedence, bool may_be_sink,
		  bool may_be_composite_lit, bool* is_type_switch,
		  bool *is_parenthesized)
{
  Expression* left = this->unary_expr(may_be_sink, may_be_composite_lit,
				      is_type_switch, is_parenthesized);

  while (true)
    {
      if (is_type_switch != NULL && *is_type_switch)
	return left;

      const Token* token = this->peek_token();
      if (token->classification() != Token::TOKEN_OPERATOR)
	{
	  // Not a binary_op.
	  return left;
	}

      Precedence right_precedence;
      switch (token->op())
	{
	case OPERATOR_OROR:
	  right_precedence = PRECEDENCE_OROR;
	  break;
	case OPERATOR_ANDAND:
	  right_precedence = PRECEDENCE_ANDAND;
	  break;
	case OPERATOR_EQEQ:
	case OPERATOR_NOTEQ:
	case OPERATOR_LT:
	case OPERATOR_LE:
	case OPERATOR_GT:
	case OPERATOR_GE:
	  right_precedence = PRECEDENCE_RELOP;
	  break;
	case OPERATOR_PLUS:
	case OPERATOR_MINUS:
	case OPERATOR_OR:
	case OPERATOR_XOR:
	  right_precedence = PRECEDENCE_ADDOP;
	  break;
	case OPERATOR_MULT:
	case OPERATOR_DIV:
	case OPERATOR_MOD:
	case OPERATOR_LSHIFT:
	case OPERATOR_RSHIFT:
	case OPERATOR_AND:
	case OPERATOR_BITCLEAR:
	  right_precedence = PRECEDENCE_MULOP;
	  break;
	default:
	  right_precedence = PRECEDENCE_INVALID;
	  break;
	}

      if (right_precedence == PRECEDENCE_INVALID)
	{
	  // Not a binary_op.
	  return left;
	}

      if (is_parenthesized != NULL)
	*is_parenthesized = false;
      
      Operator op = token->op();
      Location binop_location = token->location();

      if (precedence >= right_precedence)
	{
	  // We've already seen A * B, and we see + C.  We want to
	  // return so that A * B becomes a group.
	  return left;
	}

      this->advance_token();

      left = this->verify_not_sink(left);
      Expression* right = this->expression(right_precedence, false,
					   may_be_composite_lit,
					   NULL, NULL);
      left = Expression::make_binary(op, left, right, binop_location);
    }
}

bool
Parse::expression_may_start_here()
{
  const Token* token = this->peek_token();
  switch (token->classification())
    {
    case Token::TOKEN_INVALID:
    case Token::TOKEN_EOF:
      return false;
    case Token::TOKEN_KEYWORD:
      switch (token->keyword())
	{
	case KEYWORD_CHAN:
	case KEYWORD_FUNC:
	case KEYWORD_MAP:
	case KEYWORD_STRUCT:
	case KEYWORD_INTERFACE:
	  return true;
	default:
	  return false;
	}
    case Token::TOKEN_IDENTIFIER:
      return true;
    case Token::TOKEN_STRING:
      return true;
    case Token::TOKEN_OPERATOR:
      switch (token->op())
	{
	case OPERATOR_PLUS:
	case OPERATOR_MINUS:
	case OPERATOR_NOT:
	case OPERATOR_XOR:
	case OPERATOR_MULT:
	case OPERATOR_CHANOP:
	case OPERATOR_AND:
	case OPERATOR_LPAREN:
	case OPERATOR_LSQUARE:
	  return true;
	default:
	  return false;
	}
    case Token::TOKEN_CHARACTER:
    case Token::TOKEN_INTEGER:
    case Token::TOKEN_FLOAT:
    case Token::TOKEN_IMAGINARY:
      return true;
    default:
      go_unreachable();
    }
}

// UnaryExpr = unary_op UnaryExpr | PrimaryExpr .

// If MAY_BE_SINK is true, this expression may be "_".

// If MAY_BE_COMPOSITE_LIT is true, this expression may be a composite
// literal.

// If IS_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").

// If IS_PARENTHESIZED is not NULL, *IS_PARENTHESIZED is set to true
// if the entire expression is in parentheses.

Expression*
Parse::unary_expr(bool may_be_sink, bool may_be_composite_lit,
		  bool* is_type_switch, bool* is_parenthesized)
{
  const Token* token = this->peek_token();

  // There is a complex parse for <- chan.  The choices are
  // Convert x to type <- chan int:
  //   (<- chan int)(x)         
  // Receive from (x converted to type chan <- chan int):
  //   (<- chan <- chan int (x))
  // Convert x to type <- chan (<- chan int).
  //   (<- chan <- chan int)(x)
  if (token->is_op(OPERATOR_CHANOP))
    {
      Location location = token->location();
      if (this->advance_token()->is_keyword(KEYWORD_CHAN))
	{
	  Expression* expr = this->primary_expr(false, may_be_composite_lit,
						NULL, NULL);
	  if (expr->is_error_expression())
	    return expr;
	  else if (!expr->is_type_expression())
	    return Expression::make_receive(expr, location);
	  else
	    {
	      if (expr->type()->is_error_type())
		return expr;

	      // We picked up "chan TYPE", but it is not a type
	      // conversion.
	      Channel_type* ct = expr->type()->channel_type();
	      if (ct == NULL)
		{
		  // This is probably impossible.
		  go_error_at(location, "expected channel type");
		  return Expression::make_error(location);
		}
	      else if (ct->may_receive())
		{
		  // <- chan TYPE.
		  Type* t = Type::make_channel_type(false, true,
						    ct->element_type());
		  return Expression::make_type(t, location);
		}
	      else
		{
		  // <- chan <- TYPE.  Because we skipped the leading
		  // <-, we parsed this as chan <- TYPE.  With the
		  // leading <-, we parse it as <- chan (<- TYPE).
		  Type *t = this->reassociate_chan_direction(ct, location);
		  return Expression::make_type(t, location);
		}
	    }
	}

      this->unget_token(Token::make_operator_token(OPERATOR_CHANOP, location));
      token = this->peek_token();
    }

  if (token->is_op(OPERATOR_PLUS)
      || token->is_op(OPERATOR_MINUS)
      || token->is_op(OPERATOR_NOT)
      || token->is_op(OPERATOR_XOR)
      || token->is_op(OPERATOR_CHANOP)
      || token->is_op(OPERATOR_MULT)
      || token->is_op(OPERATOR_AND))
    {
      Location location = token->location();
      Operator op = token->op();
      this->advance_token();

      Expression* expr = this->unary_expr(false, may_be_composite_lit, NULL,
					  NULL);
      if (expr->is_error_expression())
	;
      else if (op == OPERATOR_MULT && expr->is_type_expression())
	expr = Expression::make_type(Type::make_pointer_type(expr->type()),
				     location);
      else if (op == OPERATOR_AND && expr->is_composite_literal())
	expr = Expression::make_heap_expression(expr, location);
      else if (op != OPERATOR_CHANOP)
	expr = Expression::make_unary(op, expr, location);
      else
	expr = Expression::make_receive(expr, location);
      return expr;
    }
  else
    return this->primary_expr(may_be_sink, may_be_composite_lit,
			      is_type_switch, is_parenthesized);
}

// This is called for the obscure case of
//   (<- chan <- chan int)(x)
// In unary_expr we remove the leading <- and parse the remainder,
// which gives us
//   chan <- (chan int)
// When we add the leading <- back in, we really want
//   <- chan (<- chan int)
// This means that we need to reassociate.

Type*
Parse::reassociate_chan_direction(Channel_type *ct, Location location)
{
  Channel_type* ele = ct->element_type()->channel_type();
  if (ele == NULL)
    {
      go_error_at(location, "parse error");
      return Type::make_error_type();
    }
  Type* sub = ele;
  if (ele->may_send())
    sub = Type::make_channel_type(false, true, ele->element_type());
  else
    sub = this->reassociate_chan_direction(ele, location);
  return Type::make_channel_type(false, true, sub);
}

// Statement =
//	Declaration | LabeledStmt | SimpleStmt |
//	GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
//	FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
//	DeferStmt .

// LABEL is the label of this statement if it has one.

void
Parse::statement(Label* label)
{
  const Token* token = this->peek_token();
  switch (token->classification())
    {
    case Token::TOKEN_KEYWORD:
      {
	switch (token->keyword())
	  {
	  case KEYWORD_CONST:
	  case KEYWORD_TYPE:
	  case KEYWORD_VAR:
	    this->declaration();
	    break;
	  case KEYWORD_FUNC:
	  case KEYWORD_MAP:
	  case KEYWORD_STRUCT:
	  case KEYWORD_INTERFACE:
	    this->simple_stat(true, NULL, NULL, NULL);
	    break;
	  case KEYWORD_GO:
	  case KEYWORD_DEFER:
	    this->go_or_defer_stat();
	    break;
	  case KEYWORD_RETURN:
	    this->return_stat();
	    break;
	  case KEYWORD_BREAK:
	    this->break_stat();
	    break;
	  case KEYWORD_CONTINUE:
	    this->continue_stat();
	    break;
	  case KEYWORD_GOTO:
	    this->goto_stat();
	    break;
	  case KEYWORD_IF:
	    this->if_stat();
	    break;
	  case KEYWORD_SWITCH:
	    this->switch_stat(label);
	    break;
	  case KEYWORD_SELECT:
	    this->select_stat(label);
	    break;
	  case KEYWORD_FOR:
	    this->for_stat(label);
	    break;
	  default:
	    go_error_at(this->location(), "expected statement");
	    this->advance_token();
	    break;
	  }
      }
      break;

    case Token::TOKEN_IDENTIFIER:
      {
	std::string identifier = token->identifier();
	bool is_exported = token->is_identifier_exported();
	Location location = token->location();
	if (this->advance_token()->is_op(OPERATOR_COLON))
	  {
	    this->advance_token();
	    this->labeled_stmt(identifier, location);
	  }
	else
	  {
	    this->unget_token(Token::make_identifier_token(identifier,
							   is_exported,
							   location));
	    this->simple_stat(true, NULL, NULL, NULL);
	  }
      }
      break;

    case Token::TOKEN_OPERATOR:
      if (token->is_op(OPERATOR_LCURLY))
	{
	  Location location = token->location();
	  this->gogo_->start_block(location);
	  Location end_loc = this->block();
	  this->gogo_->add_block(this->gogo_->finish_block(end_loc),
				 location);
	}
      else if (!token->is_op(OPERATOR_SEMICOLON))
	this->simple_stat(true, NULL, NULL, NULL);
      break;

    case Token::TOKEN_STRING:
    case Token::TOKEN_CHARACTER:
    case Token::TOKEN_INTEGER:
    case Token::TOKEN_FLOAT:
    case Token::TOKEN_IMAGINARY:
      this->simple_stat(true, NULL, NULL, NULL);
      break;

    default:
      go_error_at(this->location(), "expected statement");
      this->advance_token();
      break;
    }
}

bool
Parse::statement_may_start_here()
{
  const Token* token = this->peek_token();
  switch (token->classification())
    {
    case Token::TOKEN_KEYWORD:
      {
	switch (token->keyword())
	  {
	  case KEYWORD_CONST:
	  case KEYWORD_TYPE:
	  case KEYWORD_VAR:
	  case KEYWORD_FUNC:
	  case KEYWORD_MAP:
	  case KEYWORD_STRUCT:
	  case KEYWORD_INTERFACE:
	  case KEYWORD_GO:
	  case KEYWORD_DEFER:
	  case KEYWORD_RETURN:
	  case KEYWORD_BREAK:
	  case KEYWORD_CONTINUE:
	  case KEYWORD_GOTO:
	  case KEYWORD_IF:
	  case KEYWORD_SWITCH:
	  case KEYWORD_SELECT:
	  case KEYWORD_FOR:
	    return true;

	  default:
	    return false;
	  }
      }
      break;

    case Token::TOKEN_IDENTIFIER:
      return true;

    case Token::TOKEN_OPERATOR:
      if (token->is_op(OPERATOR_LCURLY)
	  || token->is_op(OPERATOR_SEMICOLON))
	return true;
      else
	return this->expression_may_start_here();

    case Token::TOKEN_STRING:
    case Token::TOKEN_CHARACTER:
    case Token::TOKEN_INTEGER:
    case Token::TOKEN_FLOAT:
    case Token::TOKEN_IMAGINARY:
      return true;

    default:
      return false;
    }
}

// LabeledStmt = Label ":" Statement .
// Label       = identifier .

void
Parse::labeled_stmt(const std::string& label_name, Location location)
{
  Label* label = this->gogo_->add_label_definition(label_name, location);

  if (this->peek_token()->is_op(OPERATOR_RCURLY))
    {
      // This is a label at the end of a block.  A program is
      // permitted to omit a semicolon here.
      return;
    }

  if (!this->statement_may_start_here())
    {
      if (this->peek_token()->is_keyword(KEYWORD_FALLTHROUGH))
	{
	  // We don't treat the fallthrough keyword as a statement,
	  // because it can't appear most places where a statement is
	  // permitted, but it may have a label.  We introduce a
	  // semicolon because the caller expects to see a statement.
	  this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON,
						       location));
	  return;
	}

      // Mark the label as used to avoid a useless error about an
      // unused label.
      if (label != NULL)
        label->set_is_used();

      go_error_at(location, "missing statement after label");
      this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON,
						   location));
      return;
    }

  this->statement(label);
}

// SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt |
//	Assignment | ShortVarDecl .

// EmptyStmt was handled in Parse::statement.

// In order to make this work for if and switch statements, if
// RETURN_EXP is not NULL, and we see an ExpressionStat, we return the
// expression rather than adding an expression statement to the
// current block.  If we see something other than an ExpressionStat,
// we add the statement, set *RETURN_EXP to true if we saw a send
// statement, and return NULL.  The handling of send statements is for
// better error messages.

// If P_RANGE_CLAUSE is not NULL, then this will recognize a
// RangeClause.

// If P_TYPE_SWITCH is not NULL, this will recognize a type switch
// guard (var := expr.("type") using the literal keyword "type").

Expression*
Parse::simple_stat(bool may_be_composite_lit, bool* return_exp,
		   Range_clause* p_range_clause, Type_switch* p_type_switch)
{
  const Token* token = this->peek_token();

  // An identifier follow by := is a SimpleVarDecl.
  if (token->is_identifier())
    {
      std::string identifier = token->identifier();
      bool is_exported = token->is_identifier_exported();
      Location location = token->location();

      token = this->advance_token();
      if (token->is_op(OPERATOR_COLONEQ)
	  || token->is_op(OPERATOR_COMMA))
	{
	  identifier = this->gogo_->pack_hidden_name(identifier, is_exported);
	  this->simple_var_decl_or_assignment(identifier, location,
					      may_be_composite_lit,
					      p_range_clause,
					      (token->is_op(OPERATOR_COLONEQ)
					       ? p_type_switch
					       : NULL));
	  return NULL;
	}

      this->unget_token(Token::make_identifier_token(identifier, is_exported,
						     location));
    }
  else if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE))
    {
      Typed_identifier_list til;
      this->range_clause_decl(&til, p_range_clause);
      return NULL;
    }

  Expression* exp = this->expression(PRECEDENCE_NORMAL, true,
				     may_be_composite_lit,
				     (p_type_switch == NULL
				      ? NULL
				      : &p_type_switch->found),
				     NULL);
  if (p_type_switch != NULL && p_type_switch->found)
    {
      p_type_switch->name.clear();
      p_type_switch->location = exp->location();
      p_type_switch->expr = this->verify_not_sink(exp);
      return NULL;
    }
  token = this->peek_token();
  if (token->is_op(OPERATOR_CHANOP))
    {
      this->send_stmt(this->verify_not_sink(exp), may_be_composite_lit);
      if (return_exp != NULL)
	*return_exp = true;
    }
  else if (token->is_op(OPERATOR_PLUSPLUS)
	   || token->is_op(OPERATOR_MINUSMINUS))
    this->inc_dec_stat(this->verify_not_sink(exp));
  else if (token->is_op(OPERATOR_COMMA)
	   || token->is_op(OPERATOR_EQ))
    this->assignment(exp, may_be_composite_lit, p_range_clause);
  else if (token->is_op(OPERATOR_PLUSEQ)
	   || token->is_op(OPERATOR_MINUSEQ)
	   || token->is_op(OPERATOR_OREQ)
	   || token->is_op(OPERATOR_XOREQ)
	   || token->is_op(OPERATOR_MULTEQ)
	   || token->is_op(OPERATOR_DIVEQ)
	   || token->is_op(OPERATOR_MODEQ)
	   || token->is_op(OPERATOR_LSHIFTEQ)
	   || token->is_op(OPERATOR_RSHIFTEQ)
	   || token->is_op(OPERATOR_ANDEQ)
	   || token->is_op(OPERATOR_BITCLEAREQ))
    this->assignment(this->verify_not_sink(exp), may_be_composite_lit,
		     p_range_clause);
  else if (return_exp != NULL)
    return this->verify_not_sink(exp);
  else
    {
      exp = this->verify_not_sink(exp);

      if (token->is_op(OPERATOR_COLONEQ))
	{
	  if (!exp->is_error_expression())
	    go_error_at(token->location(), "non-name on left side of %<:=%>");
	  this->gogo_->mark_locals_used();
	  while (!token->is_op(OPERATOR_SEMICOLON)
		 && !token->is_eof())
	    token = this->advance_token();
	  return NULL;
	}

      this->expression_stat(exp);
    }

  return NULL;
}

bool
Parse::simple_stat_may_start_here()
{
  return this->expression_may_start_here();
}

// Parse { Statement ";" } which is used in a few places.  The list of
// statements may end with a right curly brace, in which case the
// semicolon may be omitted.

void
Parse::statement_list()
{
  while (this->statement_may_start_here())
    {
      this->statement(NULL);
      if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
	this->advance_token();
      else if (this->peek_token()->is_op(OPERATOR_RCURLY))
	break;
      else
	{
	  if (!this->peek_token()->is_eof() || !saw_errors())
	    go_error_at(this->location(), "expected %<;%> or %<}%> or newline");
	  if (!this->skip_past_error(OPERATOR_RCURLY))
	    return;
	}
    }
}

bool
Parse::statement_list_may_start_here()
{
  return this->statement_may_start_here();
}

// ExpressionStat = Expression .

void
Parse::expression_stat(Expression* exp)
{
  this->gogo_->add_statement(Statement::make_statement(exp, false));
}

// SendStmt = Channel "&lt;-" Expression .
// Channel  = Expression .

void
Parse::send_stmt(Expression* channel, bool may_be_composite_lit)
{
  go_assert(this->peek_token()->is_op(OPERATOR_CHANOP));
  Location loc = this->location();
  this->advance_token();
  Expression* val = this->expression(PRECEDENCE_NORMAL, false,
				     may_be_composite_lit, NULL, NULL);
  Statement* s = Statement::make_send_statement(channel, val, loc);
  this->gogo_->add_statement(s);
}

// IncDecStat = Expression ( "++" | "--" ) .

void
Parse::inc_dec_stat(Expression* exp)
{
  const Token* token = this->peek_token();
  if (token->is_op(OPERATOR_PLUSPLUS))
    this->gogo_->add_statement(Statement::make_inc_statement(exp));
  else if (token->is_op(OPERATOR_MINUSMINUS))
    this->gogo_->add_statement(Statement::make_dec_statement(exp));
  else
    go_unreachable();
  this->advance_token();
}

// Assignment = ExpressionList assign_op ExpressionList .

// EXP is an expression that we have already parsed.

// If MAY_BE_COMPOSITE_LIT is true, an expression on the right hand
// side may be a composite literal.

// If RANGE_CLAUSE is not NULL, then this will recognize a
// RangeClause.

void
Parse::assignment(Expression* expr, bool may_be_composite_lit,
		  Range_clause* p_range_clause)
{
  Expression_list* vars;
  if (!this->peek_token()->is_op(OPERATOR_COMMA))
    {
      vars = new Expression_list();
      vars->push_back(expr);
    }
  else
    {
      this->advance_token();
      vars = this->expression_list(expr, true, may_be_composite_lit);
    }

  this->tuple_assignment(vars, may_be_composite_lit, p_range_clause);
}

// An assignment statement.  LHS is the list of expressions which
// appear on the left hand side.

// If MAY_BE_COMPOSITE_LIT is true, an expression on the right hand
// side may be a composite literal.

// If RANGE_CLAUSE is not NULL, then this will recognize a
// RangeClause.

void
Parse::tuple_assignment(Expression_list* lhs, bool may_be_composite_lit,
			Range_clause* p_range_clause)
{
  const Token* token = this->peek_token();
  if (!token->is_op(OPERATOR_EQ)
      && !token->is_op(OPERATOR_PLUSEQ)
      && !token->is_op(OPERATOR_MINUSEQ)
      && !token->is_op(OPERATOR_OREQ)
      && !token->is_op(OPERATOR_XOREQ)
      && !token->is_op(OPERATOR_MULTEQ)
      && !token->is_op(OPERATOR_DIVEQ)
      && !token->is_op(OPERATOR_MODEQ)
      && !token->is_op(OPERATOR_LSHIFTEQ)
      && !token->is_op(OPERATOR_RSHIFTEQ)
      && !token->is_op(OPERATOR_ANDEQ)
      && !token->is_op(OPERATOR_BITCLEAREQ))
    {
      go_error_at(this->location(), "expected assignment operator");
      return;
    }
  Operator op = token->op();
  Location location = token->location();

  token = this->advance_token();

  if (lhs == NULL)
    return;

  if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE))
    {
      if (op != OPERATOR_EQ)
	go_error_at(this->location(), "range clause requires %<=%>");
      this->range_clause_expr(lhs, p_range_clause);
      return;
    }

  Expression_list* vals = this->expression_list(NULL, false,
						may_be_composite_lit);

  // We've parsed everything; check for errors.
  if (vals == NULL)
    return;
  for (Expression_list::const_iterator pe = lhs->begin();
       pe != lhs->end();
       ++pe)
    {
      if ((*pe)->is_error_expression())
	return;
      if (op != OPERATOR_EQ && (*pe)->is_sink_expression())
	go_error_at((*pe)->location(), "cannot use _ as value");
    }
  for (Expression_list::const_iterator pe = vals->begin();
       pe != vals->end();
       ++pe)
    {
      if ((*pe)->is_error_expression())
	return;
    }

  Call_expression* call;
  Index_expression* map_index;
  Receive_expression* receive;
  Type_guard_expression* type_guard;
  if (lhs->size() == vals->size())
    {
      Statement* s;
      if (lhs->size() > 1)
	{
	  if (op != OPERATOR_EQ)
	    go_error_at(location, "multiple values only permitted with %<=%>");
	  s = Statement::make_tuple_assignment(lhs, vals, location);
	}
      else
	{
	  if (op == OPERATOR_EQ)
	    s = Statement::make_assignment(lhs->front(), vals->front(),
					   location);
	  else
	    s = Statement::make_assignment_operation(op, lhs->front(),
						     vals->front(), location);
	  delete lhs;
	  delete vals;
	}
      this->gogo_->add_statement(s);
    }
  else if (vals->size() == 1
	   && (call = (*vals->begin())->call_expression()) != NULL)
    {
      if (op != OPERATOR_EQ)
	go_error_at(location, "multiple results only permitted with %<=%>");
      call->set_expected_result_count(lhs->size());
      delete vals;
      vals = new Expression_list;
      for (unsigned int i = 0; i < lhs->size(); ++i)
	vals->push_back(Expression::make_call_result(call, i));
      Statement* s = Statement::make_tuple_assignment(lhs, vals, location);
      this->gogo_->add_statement(s);
    }
  else if (lhs->size() == 2
	   && vals->size() == 1
	   && (map_index = (*vals->begin())->index_expression()) != NULL)
    {
      if (op != OPERATOR_EQ)
	go_error_at(location, "two values from map requires %<=%>");
      Expression* val = lhs->front();
      Expression* present = lhs->back();
      Statement* s = Statement::make_tuple_map_assignment(val, present,
							  map_index, location);
      this->gogo_->add_statement(s);
    }
  else if (lhs->size() == 2
	   && vals->size() == 1
	   && (receive = (*vals->begin())->receive_expression()) != NULL)
    {
      if (op != OPERATOR_EQ)
	go_error_at(location, "two values from receive requires %<=%>");
      Expression* val = lhs->front();
      Expression* success = lhs->back();
      Expression* channel = receive->channel();
      Statement* s = Statement::make_tuple_receive_assignment(val, success,
							      channel,
							      location);
      this->gogo_->add_statement(s);
    }
  else if (lhs->size() == 2
	   && vals->size() == 1
	   && (type_guard = (*vals->begin())->type_guard_expression()) != NULL)
    {
      if (op != OPERATOR_EQ)
	go_error_at(location, "two values from type guard requires %<=%>");
      Expression* val = lhs->front();
      Expression* ok = lhs->back();
      Expression* expr = type_guard->expr();
      Type* type = type_guard->type();
      Statement* s = Statement::make_tuple_type_guard_assignment(val, ok,
								 expr, type,
								 location);
      this->gogo_->add_statement(s);
    }
  else
    {
      go_error_at(location, ("number of variables does not "
                             "match number of values"));
    }
}

// GoStat = "go" Expression .
// DeferStat = "defer" Expression .

void
Parse::go_or_defer_stat()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_GO)
	     || this->peek_token()->is_keyword(KEYWORD_DEFER));
  bool is_go = this->peek_token()->is_keyword(KEYWORD_GO);
  Location stat_location = this->location();

  this->advance_token();
  Location expr_location = this->location();

  bool is_parenthesized = false;
  Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true, NULL,
				      &is_parenthesized);
  Call_expression* call_expr = expr->call_expression();
  if (is_parenthesized || call_expr == NULL)
    {
      go_error_at(expr_location, "argument to go/defer must be function call");
      return;
    }

  // Make it easier to simplify go/defer statements by putting every
  // statement in its own block.
  this->gogo_->start_block(stat_location);
  Statement* stat;
  if (is_go)
    stat = Statement::make_go_statement(call_expr, stat_location);
  else
    stat = Statement::make_defer_statement(call_expr, stat_location);
  this->gogo_->add_statement(stat);
  this->gogo_->add_block(this->gogo_->finish_block(stat_location),
			 stat_location);
}

// ReturnStat = "return" [ ExpressionList ] .

void
Parse::return_stat()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_RETURN));
  Location location = this->location();
  this->advance_token();
  Expression_list* vals = NULL;
  if (this->expression_may_start_here())
    vals = this->expression_list(NULL, false, true);
  this->gogo_->add_statement(Statement::make_return_statement(vals, location));

  if (vals == NULL
      && this->gogo_->current_function()->func_value()->results_are_named())
    {
      Named_object* function = this->gogo_->current_function();
      Function::Results* results = function->func_value()->result_variables();
      for (Function::Results::const_iterator p = results->begin();
	   p != results->end();
	   ++p)
	{
	  Named_object* no = this->gogo_->lookup((*p)->name(), NULL);
	  if (no == NULL)
	    go_assert(saw_errors());
	  else if (!no->is_result_variable())
	    go_error_at(location, "%qs is shadowed during return",
			(*p)->message_name().c_str());
	}
    }
}

// IfStmt = "if" [ SimpleStmt ";" ] Expression Block
//          [ "else" ( IfStmt | Block ) ] .

void
Parse::if_stat()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_IF));
  Location location = this->location();
  this->advance_token();

  this->gogo_->start_block(location);

  bool saw_simple_stat = false;
  Expression* cond = NULL;
  bool saw_send_stmt = false;
  if (this->simple_stat_may_start_here())
    {
      cond = this->simple_stat(false, &saw_send_stmt, NULL, NULL);
      saw_simple_stat = true;
    }
  if (cond != NULL && this->peek_token()->is_op(OPERATOR_SEMICOLON))
    {
      // The SimpleStat is an expression statement.
      this->expression_stat(cond);
      cond = NULL;
    }
  if (cond == NULL)
    {
      if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
	this->advance_token();
      else if (saw_simple_stat)
	{
	  if (saw_send_stmt)
	    go_error_at(this->location(),
			("send statement used as value; "
			 "use select for non-blocking send"));
	  else
	    go_error_at(this->location(),
			"expected %<;%> after statement in if expression");
	  if (!this->expression_may_start_here())
	    cond = Expression::make_error(this->location());
	}
      if (cond == NULL && this->peek_token()->is_op(OPERATOR_LCURLY))
	{
	  go_error_at(this->location(),
		      "missing condition in if statement");
	  cond = Expression::make_error(this->location());
	}
      if (cond == NULL)
	cond = this->expression(PRECEDENCE_NORMAL, false, false, NULL, NULL);
    }

  // Check for the easy error of a newline before starting the block.
  if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
    {
      Location semi_loc = this->location();
      if (this->advance_token()->is_op(OPERATOR_LCURLY))
	go_error_at(semi_loc, "missing %<{%> after if clause");
      // Otherwise we will get an error when we call this->block
      // below.
    }

  this->gogo_->start_block(this->location());
  Location end_loc = this->block();
  Block* then_block = this->gogo_->finish_block(end_loc);

  // Check for the easy error of a newline before "else".
  if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
    {
      Location semi_loc = this->location();
      if (this->advance_token()->is_keyword(KEYWORD_ELSE))
	go_error_at(this->location(),
		 "unexpected semicolon or newline before %<else%>");
      else
	this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON,
						     semi_loc));
    }

  Block* else_block = NULL;
  if (this->peek_token()->is_keyword(KEYWORD_ELSE))
    {
      this->gogo_->start_block(this->location());
      const Token* token = this->advance_token();
      if (token->is_keyword(KEYWORD_IF))
	this->if_stat();
      else if (token->is_op(OPERATOR_LCURLY))
	this->block();
      else
	{
	  go_error_at(this->location(), "expected %<if%> or %<{%>");
	  this->statement(NULL);
	}
      else_block = this->gogo_->finish_block(this->location());
    }

  this->gogo_->add_statement(Statement::make_if_statement(cond, then_block,
							  else_block,
							  location));

  this->gogo_->add_block(this->gogo_->finish_block(this->location()),
			 location);
}

// SwitchStmt = ExprSwitchStmt | TypeSwitchStmt .
// ExprSwitchStmt = "switch" [ [ SimpleStat ] ";" ] [ Expression ]
//			"{" { ExprCaseClause } "}" .
// TypeSwitchStmt  = "switch" [ [ SimpleStat ] ";" ] TypeSwitchGuard
//			"{" { TypeCaseClause } "}" .
// TypeSwitchGuard = [ identifier ":=" ] Expression "." "(" "type" ")" .

void
Parse::switch_stat(Label* label)
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_SWITCH));
  Location location = this->location();
  this->advance_token();

  this->gogo_->start_block(location);

  bool saw_simple_stat = false;
  Expression* switch_val = NULL;
  bool saw_send_stmt;
  Type_switch type_switch;
  bool have_type_switch_block = false;
  if (this->simple_stat_may_start_here())
    {
      switch_val = this->simple_stat(false, &saw_send_stmt, NULL,
				     &type_switch);
      saw_simple_stat = true;
    }
  if (switch_val != NULL && this->peek_token()->is_op(OPERATOR_SEMICOLON))
    {
      // The SimpleStat is an expression statement.
      this->expression_stat(switch_val);
      switch_val = NULL;
    }
  if (switch_val == NULL && !type_switch.found)
    {
      if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
	this->advance_token();
      else if (saw_simple_stat)
	{
	  if (saw_send_stmt)
	    go_error_at(this->location(),
			("send statement used as value; "
			 "use select for non-blocking send"));
	  else
	    go_error_at(this->location(),
			"expected %<;%> after statement in switch expression");
	}
      if (!this->peek_token()->is_op(OPERATOR_LCURLY))
	{
	  if (this->peek_token()->is_identifier())
	    {
	      const Token* token = this->peek_token();
	      std::string identifier = token->identifier();
	      bool is_exported = token->is_identifier_exported();
	      Location id_loc = token->location();

	      token = this->advance_token();
	      bool is_coloneq = token->is_op(OPERATOR_COLONEQ);
	      this->unget_token(Token::make_identifier_token(identifier,
							     is_exported,
							     id_loc));
	      if (is_coloneq)
		{
		  // This must be a TypeSwitchGuard.  It is in a
		  // different block from any initial SimpleStat.
		  if (saw_simple_stat)
		    {
		      this->gogo_->start_block(id_loc);
		      have_type_switch_block = true;
		    }

		  switch_val = this->simple_stat(false, &saw_send_stmt, NULL,
						 &type_switch);
		  if (!type_switch.found)
		    {
		      if (switch_val == NULL
			  || !switch_val->is_error_expression())
			{
			  go_error_at(id_loc,
				      "expected type switch assignment");
			  switch_val = Expression::make_error(id_loc);
			}
		    }
		}
	    }
	  if (switch_val == NULL && !type_switch.found)
	    {
	      switch_val = this->expression(PRECEDENCE_NORMAL, false, false,
					    &type_switch.found, NULL);
	      if (type_switch.found)
		{
		  type_switch.name.clear();
		  type_switch.expr = switch_val;
		  type_switch.location = switch_val->location();
		}
	    }
	}
    }

  if (!this->peek_token()->is_op(OPERATOR_LCURLY))
    {
      Location token_loc = this->location();
      if (this->peek_token()->is_op(OPERATOR_SEMICOLON)
	  && this->advance_token()->is_op(OPERATOR_LCURLY))
	go_error_at(token_loc, "missing %<{%> after switch clause");
      else if (this->peek_token()->is_op(OPERATOR_COLONEQ))
	{
	  go_error_at(token_loc, "invalid variable name");
	  this->advance_token();
	  this->expression(PRECEDENCE_NORMAL, false, false,
			   &type_switch.found, NULL);
	  if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
	    this->advance_token();
	  if (!this->peek_token()->is_op(OPERATOR_LCURLY))
	    {
	      if (have_type_switch_block)
		this->gogo_->add_block(this->gogo_->finish_block(location),
				       location);
	      this->gogo_->add_block(this->gogo_->finish_block(location),
				     location);
	      return;
	    }
	  if (type_switch.found)
	    type_switch.expr = Expression::make_error(location);
	}
      else
	{
	  go_error_at(this->location(), "expected %<{%>");
	  if (have_type_switch_block)
	    this->gogo_->add_block(this->gogo_->finish_block(this->location()),
				   location);
	  this->gogo_->add_block(this->gogo_->finish_block(this->location()),
				 location);
	  return;
	}
    }
  this->advance_token();

  Statement* statement;
  if (type_switch.found)
    statement = this->type_switch_body(label, type_switch, location);
  else
    statement = this->expr_switch_body(label, switch_val, location);

  if (statement != NULL)
    this->gogo_->add_statement(statement);

  if (have_type_switch_block)
    this->gogo_->add_block(this->gogo_->finish_block(this->location()),
			   location);

  this->gogo_->add_block(this->gogo_->finish_block(this->location()),
			 location);
}

// The body of an expression switch.
//   "{" { ExprCaseClause } "}"

Statement*
Parse::expr_switch_body(Label* label, Expression* switch_val,
			Location location)
{
  Switch_statement* statement = Statement::make_switch_statement(switch_val,
								 location);

  this->push_break_statement(statement, label);

  Case_clauses* case_clauses = new Case_clauses();
  bool saw_default = false;
  while (!this->peek_token()->is_op(OPERATOR_RCURLY))
    {
      if (this->peek_token()->is_eof())
	{
	  if (!saw_errors())
	    go_error_at(this->location(), "missing %<}%>");
	  return NULL;
	}
      this->expr_case_clause(case_clauses, &saw_default);
    }
  this->advance_token();

  statement->add_clauses(case_clauses);

  this->pop_break_statement();

  return statement;
}

// ExprCaseClause = ExprSwitchCase ":" [ StatementList ] .
// FallthroughStat = "fallthrough" .

void
Parse::expr_case_clause(Case_clauses* clauses, bool* saw_default)
{
  Location location = this->location();

  bool is_default = false;
  Expression_list* vals = this->expr_switch_case(&is_default);

  if (!this->peek_token()->is_op(OPERATOR_COLON))
    {
      if (!saw_errors())
	go_error_at(this->location(), "expected %<:%>");
      return;
    }
  else
    this->advance_token();

  Block* statements = NULL;
  if (this->statement_list_may_start_here())
    {
      this->gogo_->start_block(this->location());
      this->statement_list();
      statements = this->gogo_->finish_block(this->location());
    }

  bool is_fallthrough = false;
  if (this->peek_token()->is_keyword(KEYWORD_FALLTHROUGH))
    {
      Location fallthrough_loc = this->location();
      is_fallthrough = true;
      if (this->advance_token()->is_op(OPERATOR_SEMICOLON))
	this->advance_token();
      if (this->peek_token()->is_op(OPERATOR_RCURLY))
	go_error_at(fallthrough_loc,
		    _("cannot fallthrough final case in switch"));
    }

  if (is_default)
    {
      if (*saw_default)
	{
	  go_error_at(location, "multiple defaults in switch");
	  return;
	}
      *saw_default = true;
    }

  if (is_default || vals != NULL)
    clauses->add(vals, is_default, statements, is_fallthrough, location);
}

// ExprSwitchCase = "case" ExpressionList | "default" .

Expression_list*
Parse::expr_switch_case(bool* is_default)
{
  const Token* token = this->peek_token();
  if (token->is_keyword(KEYWORD_CASE))
    {
      this->advance_token();
      return this->expression_list(NULL, false, true);
    }
  else if (token->is_keyword(KEYWORD_DEFAULT))
    {
      this->advance_token();
      *is_default = true;
      return NULL;
    }
  else
    {
      if (!saw_errors())
	go_error_at(this->location(), "expected %<case%> or %<default%>");
      if (!token->is_op(OPERATOR_RCURLY))
	this->advance_token();
      return NULL;
    }
}

// The body of a type switch.
//   "{" { TypeCaseClause } "}" .

Statement*
Parse::type_switch_body(Label* label, const Type_switch& type_switch,
			Location location)
{
  Expression* init = type_switch.expr;
  std::string var_name = type_switch.name;
  if (!var_name.empty())
    {
      if (Gogo::is_sink_name(var_name))
        {
	  go_error_at(type_switch.location,
		      "no new variables on left side of %<:=%>");
          var_name.clear();
        }
      else
	{
          Location loc = type_switch.location;
	  Temporary_statement* switch_temp =
              Statement::make_temporary(NULL, init, loc);
	  this->gogo_->add_statement(switch_temp);
          init = Expression::make_temporary_reference(switch_temp, loc);
	}
    }

  Type_switch_statement* statement =
      Statement::make_type_switch_statement(var_name, init, location);
  this->push_break_statement(statement, label);

  Type_case_clauses* case_clauses = new Type_case_clauses();
  bool saw_default = false;
  std::vector<Named_object*> implicit_vars;
  while (!this->peek_token()->is_op(OPERATOR_RCURLY))
    {
      if (this->peek_token()->is_eof())
	{
	  go_error_at(this->location(), "missing %<}%>");
	  return NULL;
	}
      this->type_case_clause(var_name, init, case_clauses, &saw_default,
                             &implicit_vars);
    }
  this->advance_token();

  statement->add_clauses(case_clauses);

  this->pop_break_statement();

  // If there is a type switch variable implicitly declared in each case clause,
  // check that it is used in at least one of the cases.
  if (!var_name.empty())
    {
      bool used = false;
      for (std::vector<Named_object*>::iterator p = implicit_vars.begin();
	   p != implicit_vars.end();
	   ++p)
	{
	  if ((*p)->var_value()->is_used())
	    {
	      used = true;
	      break;
	    }
	}
      if (!used)
	go_error_at(type_switch.location, "%qs declared and not used",
		    Gogo::message_name(var_name).c_str());
    }
  return statement;
}

// TypeCaseClause  = TypeSwitchCase ":" [ StatementList ] .
// IMPLICIT_VARS is the list of variables implicitly declared for each type
// case if there is a type switch variable declared.

void
Parse::type_case_clause(const std::string& var_name, Expression* init,
                        Type_case_clauses* clauses, bool* saw_default,
			std::vector<Named_object*>* implicit_vars)
{
  Location location = this->location();

  std::vector<Type*> types;
  bool is_default = false;
  this->type_switch_case(&types, &is_default);

  if (!this->peek_token()->is_op(OPERATOR_COLON))
    go_error_at(this->location(), "expected %<:%>");
  else
    this->advance_token();

  Block* statements = NULL;
  if (this->statement_list_may_start_here())
    {
      this->gogo_->start_block(this->location());
      if (!var_name.empty())
	{
	  Type* type = NULL;
          Location var_loc = init->location();
	  if (types.size() == 1)
	    {
	      type = types.front();
	      init = Expression::make_type_guard(init, type, location);
	    }

	  Variable* v = new Variable(type, init, false, false, false,
				     var_loc);
	  v->set_is_used();
	  v->set_is_type_switch_var();
	  implicit_vars->push_back(this->gogo_->add_variable(var_name, v));
	}
      this->statement_list();
      statements = this->gogo_->finish_block(this->location());
    }

  if (this->peek_token()->is_keyword(KEYWORD_FALLTHROUGH))
    {
      go_error_at(this->location(),
		  "fallthrough is not permitted in a type switch");
      if (this->advance_token()->is_op(OPERATOR_SEMICOLON))
	this->advance_token();
    }

  if (is_default)
    {
      go_assert(types.empty());
      if (*saw_default)
	{
	  go_error_at(location, "multiple defaults in type switch");
	  return;
	}
      *saw_default = true;
      clauses->add(NULL, false, true, statements, location);
    }
  else if (!types.empty())
    {
      for (std::vector<Type*>::const_iterator p = types.begin();
	   p + 1 != types.end();
	   ++p)
	clauses->add(*p, true, false, NULL, location);
      clauses->add(types.back(), false, false, statements, location);
    }
  else
    clauses->add(Type::make_error_type(), false, false, statements, location);
}

// TypeSwitchCase  = "case" type | "default"

// We accept a comma separated list of types.

void
Parse::type_switch_case(std::vector<Type*>* types, bool* is_default)
{
  const Token* token = this->peek_token();
  if (token->is_keyword(KEYWORD_CASE))
    {
      this->advance_token();
      while (true)
	{
	  Type* t = this->type();

	  if (!t->is_error_type())
	    types->push_back(t);
	  else
	    {
	      this->gogo_->mark_locals_used();
	      token = this->peek_token();
	      while (!token->is_op(OPERATOR_COLON)
		     && !token->is_op(OPERATOR_COMMA)
		     && !token->is_op(OPERATOR_RCURLY)
		     && !token->is_eof())
		token = this->advance_token();
	    }

	  if (!this->peek_token()->is_op(OPERATOR_COMMA))
	    break;
	  this->advance_token();
	}
    }
  else if (token->is_keyword(KEYWORD_DEFAULT))
    {
      this->advance_token();
      *is_default = true;
    }
  else
    {
      go_error_at(this->location(), "expected %<case%> or %<default%>");
      if (!token->is_op(OPERATOR_RCURLY))
	this->advance_token();
    }
}

// SelectStat = "select" "{" { CommClause } "}" .

void
Parse::select_stat(Label* label)
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_SELECT));
  Location location = this->location();
  const Token* token = this->advance_token();

  if (!token->is_op(OPERATOR_LCURLY))
    {
      Location token_loc = token->location();
      if (token->is_op(OPERATOR_SEMICOLON)
	  && this->advance_token()->is_op(OPERATOR_LCURLY))
	go_error_at(token_loc, "unexpected semicolon or newline before %<{%>");
      else
	{
	  go_error_at(this->location(), "expected %<{%>");
	  return;
	}
    }
  this->advance_token();

  Select_statement* statement = Statement::make_select_statement(location);

  this->push_break_statement(statement, label);

  Select_clauses* select_clauses = new Select_clauses();
  bool saw_default = false;
  while (!this->peek_token()->is_op(OPERATOR_RCURLY))
    {
      if (this->peek_token()->is_eof())
	{
	  go_error_at(this->location(), "expected %<}%>");
	  return;
	}
      this->comm_clause(select_clauses, &saw_default);
    }

  this->advance_token();

  statement->add_clauses(select_clauses);

  this->pop_break_statement();

  this->gogo_->add_statement(statement);
}

// CommClause = CommCase ":" { Statement ";" } .

void
Parse::comm_clause(Select_clauses* clauses, bool* saw_default)
{
  Location location = this->location();
  bool is_send = false;
  Expression* channel = NULL;
  Expression* val = NULL;
  Expression* closed = NULL;
  std::string varname;
  std::string closedname;
  bool is_default = false;
  bool got_case = this->comm_case(&is_send, &channel, &val, &closed,
				  &varname, &closedname, &is_default);

  if (this->peek_token()->is_op(OPERATOR_COLON))
    this->advance_token();
  else
    go_error_at(this->location(), "expected colon");

  this->gogo_->start_block(this->location());

  Named_object* var = NULL;
  if (!varname.empty())
    {
      // FIXME: LOCATION is slightly wrong here.
      Variable* v = new Variable(NULL, channel, false, false, false,
				 location);
      v->set_type_from_chan_element();
      var = this->gogo_->add_variable(varname, v);
    }

  Named_object* closedvar = NULL;
  if (!closedname.empty())
    {
      // FIXME: LOCATION is slightly wrong here.
      Variable* v = new Variable(Type::lookup_bool_type(), NULL,
				 false, false, false, location);
      closedvar = this->gogo_->add_variable(closedname, v);
    }

  this->statement_list();

  Block* statements = this->gogo_->finish_block(this->location());

  if (is_default)
    {
      if (*saw_default)
	{
	  go_error_at(location, "multiple defaults in select");
	  return;
	}
      *saw_default = true;
    }

  if (got_case)
    clauses->add(is_send, channel, val, closed, var, closedvar, is_default,
		 statements, location);
  else if (statements != NULL)
    {
      // Add the statements to make sure that any names they define
      // are traversed.
      this->gogo_->add_block(statements, location);
    }
}

// CommCase   = "case" ( SendStmt | RecvStmt ) | "default" .

bool
Parse::comm_case(bool* is_send, Expression** channel, Expression** val,
		 Expression** closed, std::string* varname,
		 std::string* closedname, bool* is_default)
{
  const Token* token = this->peek_token();
  if (token->is_keyword(KEYWORD_DEFAULT))
    {
      this->advance_token();
      *is_default = true;
    }
  else if (token->is_keyword(KEYWORD_CASE))
    {
      this->advance_token();
      if (!this->send_or_recv_stmt(is_send, channel, val, closed, varname,
				   closedname))
	return false;
    }
  else
    {
      go_error_at(this->location(), "expected %<case%> or %<default%>");
      if (!token->is_op(OPERATOR_RCURLY))
	this->advance_token();
      return false;
    }

  return true;
}

// RecvStmt   = [ Expression [ "," Expression ] ( "=" | ":=" ) ] RecvExpr .
// RecvExpr   = Expression .

bool
Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
			 Expression** closed, std::string* varname,
			 std::string* closedname)
{
  const Token* token = this->peek_token();
  bool saw_comma = false;
  bool closed_is_id = false;
  if (token->is_identifier())
    {
      Gogo* gogo = this->gogo_;
      std::string recv_var = token->identifier();
      bool is_rv_exported = token->is_identifier_exported();
      Location recv_var_loc = token->location();
      token = this->advance_token();
      if (token->is_op(OPERATOR_COLONEQ))
	{
	  // case rv := <-c:
	  this->advance_token();
	  Expression* e = this->expression(PRECEDENCE_NORMAL, false, false,
					   NULL, NULL);
	  Receive_expression* re = e->receive_expression();
	  if (re == NULL)
	    {
	      if (!e->is_error_expression())
		go_error_at(this->location(), "expected receive expression");
	      return false;
	    }
	  if (recv_var == "_")
	    {
	      go_error_at(recv_var_loc,
			  "no new variables on left side of %<:=%>");
	      recv_var = Gogo::erroneous_name();
	    }
	  *is_send = false;
	  *varname = gogo->pack_hidden_name(recv_var, is_rv_exported);
	  *channel = re->channel();
	  return true;
	}
      else if (token->is_op(OPERATOR_COMMA))
	{
	  token = this->advance_token();
	  if (token->is_identifier())
	    {
	      std::string recv_closed = token->identifier();
	      bool is_rc_exported = token->is_identifier_exported();
	      Location recv_closed_loc = token->location();
	      closed_is_id = true;

	      token = this->advance_token();
	      if (token->is_op(OPERATOR_COLONEQ))
		{
		  // case rv, rc := <-c:
		  this->advance_token();
		  Expression* e = this->expression(PRECEDENCE_NORMAL, false,
						   false, NULL, NULL);
		  Receive_expression* re = e->receive_expression();
		  if (re == NULL)
		    {
		      if (!e->is_error_expression())
			go_error_at(this->location(),
				 "expected receive expression");
		      return false;
		    }
		  if (recv_var == "_" && recv_closed == "_")
		    {
		      go_error_at(recv_var_loc,
				  "no new variables on left side of %<:=%>");
		      recv_var = Gogo::erroneous_name();
		    }
		  *is_send = false;
		  if (recv_var != "_")
		    *varname = gogo->pack_hidden_name(recv_var,
						      is_rv_exported);
		  if (recv_closed != "_")
		    *closedname = gogo->pack_hidden_name(recv_closed,
							 is_rc_exported);
		  *channel = re->channel();
		  return true;
		}

	      this->unget_token(Token::make_identifier_token(recv_closed,
							     is_rc_exported,
							     recv_closed_loc));
	    }

	  *val = this->id_to_expression(gogo->pack_hidden_name(recv_var,
							       is_rv_exported),
					recv_var_loc, true);
	  saw_comma = true;
	}
      else
	this->unget_token(Token::make_identifier_token(recv_var,
						       is_rv_exported,
						       recv_var_loc));
    }

  // If SAW_COMMA is false, then we are looking at the start of the
  // send or receive expression.  If SAW_COMMA is true, then *VAL is
  // set and we just read a comma.

  Expression* e;
  if (saw_comma || !this->peek_token()->is_op(OPERATOR_CHANOP))
    e = this->expression(PRECEDENCE_NORMAL, true, true, NULL, NULL);
  else
    {
      // case <-c:
      *is_send = false;
      this->advance_token();
      *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);

      // The next token should be ':'.  If it is '<-', then we have
      // case <-c <- v:
      // which is to say, send on a channel received from a channel.
      if (!this->peek_token()->is_op(OPERATOR_CHANOP))
	return true;

      e = Expression::make_receive(*channel, (*channel)->location());
    }

  if (!saw_comma && this->peek_token()->is_op(OPERATOR_COMMA))
    {
      this->advance_token();
      // case v, e = <-c:
      if (!e->is_sink_expression())
	*val = e;
      e = this->expression(PRECEDENCE_NORMAL, true, true, NULL, NULL);
      saw_comma = true;
    }

  if (this->peek_token()->is_op(OPERATOR_EQ))
    {
      if (!this->advance_token()->is_op(OPERATOR_CHANOP))
	{
	  go_error_at(this->location(), "missing %<<-%>");
	  return false;
	}
      *is_send = false;
      this->advance_token();
      *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
      if (saw_comma)
	{
	  // case v, e = <-c:
	  // *VAL is already set.
	  if (!e->is_sink_expression())
	    *closed = e;
	}
      else
	{
	  // case v = <-c:
	  if (!e->is_sink_expression())
	    *val = e;
	}
      return true;
    }

  if (saw_comma)
    {
      if (closed_is_id)
	go_error_at(this->location(), "expected %<=%> or %<:=%>");
      else
	go_error_at(this->location(), "expected %<=%>");
      return false;
    }

  if (this->peek_token()->is_op(OPERATOR_CHANOP))
    {
      // case c <- v:
      *is_send = true;
      *channel = this->verify_not_sink(e);
      this->advance_token();
      *val = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
      return true;
    }

  go_error_at(this->location(), "expected %<<-%> or %<=%>");
  return false;
}

// ForStat = "for" [ Condition | ForClause | RangeClause ] Block .
// Condition = Expression .

void
Parse::for_stat(Label* label)
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_FOR));
  Location location = this->location();
  const Token* token = this->advance_token();

  // Open a block to hold any variables defined in the init statement
  // of the for statement.
  this->gogo_->start_block(location);

  Block* init = NULL;
  Expression* cond = NULL;
  Block* post = NULL;
  Range_clause range_clause;

  if (!token->is_op(OPERATOR_LCURLY))
    {
      if (token->is_keyword(KEYWORD_VAR))
	{
	  go_error_at(this->location(),
                      "var declaration not allowed in for initializer");
	  this->var_decl();
	}

      if (token->is_op(OPERATOR_SEMICOLON))
	this->for_clause(&cond, &post);
      else
	{
	  // We might be looking at a Condition, an InitStat, or a
	  // RangeClause.
	  bool saw_send_stmt;
	  cond = this->simple_stat(false, &saw_send_stmt, &range_clause, NULL);
	  if (!this->peek_token()->is_op(OPERATOR_SEMICOLON))
	    {
	      if (cond == NULL && !range_clause.found)
		{
		  if (saw_send_stmt)
		    go_error_at(this->location(),
                                ("send statement used as value; "
                                 "use select for non-blocking send"));
		  else
		    go_error_at(this->location(),
                                "parse error in for statement");
		}
	    }
	  else
	    {
	      if (range_clause.found)
		go_error_at(this->location(), "parse error after range clause");

	      if (cond != NULL)
		{
		  // COND is actually an expression statement for
		  // InitStat at the start of a ForClause.
		  this->expression_stat(cond);
		  cond = NULL;
		}

	      this->for_clause(&cond, &post);
	    }
	}
    }

  // Check for the easy error of a newline before starting the block.
  if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
    {
      Location semi_loc = this->location();
      if (this->advance_token()->is_op(OPERATOR_LCURLY))
	go_error_at(semi_loc, "missing %<{%> after for clause");
      // Otherwise we will get an error when we call this->block
      // below.
    }

  // Build the For_statement and note that it is the current target
  // for break and continue statements.

  For_statement* sfor;
  For_range_statement* srange;
  Statement* s;
  if (!range_clause.found)
    {
      sfor = Statement::make_for_statement(init, cond, post, location);
      s = sfor;
      srange = NULL;
    }
  else
    {
      srange = Statement::make_for_range_statement(range_clause.index,
						   range_clause.value,
						   range_clause.range,
						   location);
      s = srange;
      sfor = NULL;
    }

  this->push_break_statement(s, label);
  this->push_continue_statement(s, label);

  // Gather the block of statements in the loop and add them to the
  // For_statement.

  this->gogo_->start_block(this->location());
  Location end_loc = this->block();
  Block* statements = this->gogo_->finish_block(end_loc);

  if (sfor != NULL)
    sfor->add_statements(statements);
  else
    srange->add_statements(statements);

  // This is no longer the break/continue target.
  this->pop_break_statement();
  this->pop_continue_statement();

  // Add the For_statement to the list of statements, and close out
  // the block we started to hold any variables defined in the for
  // statement.

  this->gogo_->add_statement(s);

  this->gogo_->add_block(this->gogo_->finish_block(this->location()),
			 location);
}

// ForClause = [ InitStat ] ";" [ Condition ] ";" [ PostStat ] .
// InitStat = SimpleStat .
// PostStat = SimpleStat .

// We have already read InitStat at this point.

void
Parse::for_clause(Expression** cond, Block** post)
{
  go_assert(this->peek_token()->is_op(OPERATOR_SEMICOLON));
  this->advance_token();
  if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
    *cond = NULL;
  else if (this->peek_token()->is_op(OPERATOR_LCURLY))
    {
      go_error_at(this->location(), "missing %<{%> after for clause");
      *cond = NULL;
      *post = NULL;
      return;
    }
  else
    *cond = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL);
  if (!this->peek_token()->is_op(OPERATOR_SEMICOLON))
    go_error_at(this->location(), "expected semicolon");
  else
    this->advance_token();

  if (this->peek_token()->is_op(OPERATOR_LCURLY))
    *post = NULL;
  else
    {
      this->gogo_->start_block(this->location());
      this->simple_stat(false, NULL, NULL, NULL);
      *post = this->gogo_->finish_block(this->location());
    }
}

// RangeClause = [ IdentifierList ( "=" | ":=" ) ] "range" Expression .

// This is the := version.  It is called with a list of identifiers.

void
Parse::range_clause_decl(const Typed_identifier_list* til,
			 Range_clause* p_range_clause)
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_RANGE));
  Location location = this->location();

  p_range_clause->found = true;

  if (til->size() > 2)
    go_error_at(this->location(), "too many variables for range clause");

  this->advance_token();
  Expression* expr = this->expression(PRECEDENCE_NORMAL, false, false, NULL,
				      NULL);
  p_range_clause->range = expr;

  if (til->empty())
    return;

  bool any_new = false;

  const Typed_identifier* pti = &til->front();
  Named_object* no = this->init_var(*pti, NULL, expr, true, true, &any_new,
				    NULL, NULL);
  if (any_new && no->is_variable())
    no->var_value()->set_type_from_range_index();
  p_range_clause->index = Expression::make_var_reference(no, location);

  if (til->size() == 1)
    p_range_clause->value = NULL;
  else
    {
      pti = &til->back();
      bool is_new = false;
      no = this->init_var(*pti, NULL, expr, true, true, &is_new, NULL, NULL);
      if (is_new && no->is_variable())
	no->var_value()->set_type_from_range_value();
      if (is_new)
	any_new = true;
      if (!Gogo::is_sink_name(pti->name()))
        p_range_clause->value = Expression::make_var_reference(no, location);
    }

  if (!any_new)
    go_error_at(location, "variables redeclared but no variable is new");
}

// The = version of RangeClause.  This is called with a list of
// expressions.

void
Parse::range_clause_expr(const Expression_list* vals,
			 Range_clause* p_range_clause)
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_RANGE));

  p_range_clause->found = true;

  go_assert(vals->size() >= 1);
  if (vals->size() > 2)
    go_error_at(this->location(), "too many variables for range clause");

  this->advance_token();
  p_range_clause->range = this->expression(PRECEDENCE_NORMAL, false, false,
					   NULL, NULL);

  if (vals->empty())
    return;

  p_range_clause->index = vals->front();
  if (vals->size() == 1)
    p_range_clause->value = NULL;
  else
    p_range_clause->value = vals->back();
}

// Push a statement on the break stack.

void
Parse::push_break_statement(Statement* enclosing, Label* label)
{
  if (this->break_stack_ == NULL)
    this->break_stack_ = new Bc_stack();
  this->break_stack_->push_back(std::make_pair(enclosing, label));
}

// Push a statement on the continue stack.

void
Parse::push_continue_statement(Statement* enclosing, Label* label)
{
  if (this->continue_stack_ == NULL)
    this->continue_stack_ = new Bc_stack();
  this->continue_stack_->push_back(std::make_pair(enclosing, label));
}

// Pop the break stack.

void
Parse::pop_break_statement()
{
  this->break_stack_->pop_back();
}

// Pop the continue stack.

void
Parse::pop_continue_statement()
{
  this->continue_stack_->pop_back();
}

// Find a break or continue statement given a label name.

Statement*
Parse::find_bc_statement(const Bc_stack* bc_stack, const std::string& label)
{
  if (bc_stack == NULL)
    return NULL;
  for (Bc_stack::const_reverse_iterator p = bc_stack->rbegin();
       p != bc_stack->rend();
       ++p)
    {
      if (p->second != NULL && p->second->name() == label)
	{
	  p->second->set_is_used();
	  return p->first;
	}
    }
  return NULL;
}

// BreakStat = "break" [ identifier ] .

void
Parse::break_stat()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_BREAK));
  Location location = this->location();

  const Token* token = this->advance_token();
  Statement* enclosing;
  if (!token->is_identifier())
    {
      if (this->break_stack_ == NULL || this->break_stack_->empty())
	{
	  go_error_at(this->location(),
                      "break statement not within for or switch or select");
	  return;
	}
      enclosing = this->break_stack_->back().first;
    }
  else
    {
      enclosing = this->find_bc_statement(this->break_stack_,
					  token->identifier());
      if (enclosing == NULL)
	{
	  // If there is a label with this name, mark it as used to
	  // avoid a useless error about an unused label.
	  this->gogo_->add_label_reference(token->identifier(),
                                           Linemap::unknown_location(), false);

	  go_error_at(token->location(), "invalid break label %qs",
                      Gogo::message_name(token->identifier()).c_str());
	  this->advance_token();
	  return;
	}
      this->advance_token();
    }

  Unnamed_label* label;
  if (enclosing->classification() == Statement::STATEMENT_FOR)
    label = enclosing->for_statement()->break_label();
  else if (enclosing->classification() == Statement::STATEMENT_FOR_RANGE)
    label = enclosing->for_range_statement()->break_label();
  else if (enclosing->classification() == Statement::STATEMENT_SWITCH)
    label = enclosing->switch_statement()->break_label();
  else if (enclosing->classification() == Statement::STATEMENT_TYPE_SWITCH)
    label = enclosing->type_switch_statement()->break_label();
  else if (enclosing->classification() == Statement::STATEMENT_SELECT)
    label = enclosing->select_statement()->break_label();
  else
    go_unreachable();

  this->gogo_->add_statement(Statement::make_break_statement(label,
							     location));
}

// ContinueStat = "continue" [ identifier ] .

void
Parse::continue_stat()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_CONTINUE));
  Location location = this->location();

  const Token* token = this->advance_token();
  Statement* enclosing;
  if (!token->is_identifier())
    {
      if (this->continue_stack_ == NULL || this->continue_stack_->empty())
	{
	  go_error_at(this->location(), "continue statement not within for");
	  return;
	}
      enclosing = this->continue_stack_->back().first;
    }
  else
    {
      enclosing = this->find_bc_statement(this->continue_stack_,
					  token->identifier());
      if (enclosing == NULL)
	{
	  // If there is a label with this name, mark it as used to
	  // avoid a useless error about an unused label.
	  this->gogo_->add_label_reference(token->identifier(),
                                           Linemap::unknown_location(), false);

	  go_error_at(token->location(), "invalid continue label %qs",
                      Gogo::message_name(token->identifier()).c_str());
	  this->advance_token();
	  return;
	}
      this->advance_token();
    }

  Unnamed_label* label;
  if (enclosing->classification() == Statement::STATEMENT_FOR)
    label = enclosing->for_statement()->continue_label();
  else if (enclosing->classification() == Statement::STATEMENT_FOR_RANGE)
    label = enclosing->for_range_statement()->continue_label();
  else
    go_unreachable();

  this->gogo_->add_statement(Statement::make_continue_statement(label,
								location));
}

// GotoStat = "goto" identifier .

void
Parse::goto_stat()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_GOTO));
  Location location = this->location();
  const Token* token = this->advance_token();
  if (!token->is_identifier())
    go_error_at(this->location(), "expected label for goto");
  else
    {
      Label* label = this->gogo_->add_label_reference(token->identifier(),
						      location, true);
      Statement* s = Statement::make_goto_statement(label, location);
      this->gogo_->add_statement(s);
      this->advance_token();
    }
}

// PackageClause = "package" PackageName .

void
Parse::package_clause()
{
  const Token* token = this->peek_token();
  Location location = token->location();
  std::string name;
  if (!token->is_keyword(KEYWORD_PACKAGE))
    {
      go_error_at(this->location(), "program must start with package clause");
      name = "ERROR";
    }
  else
    {
      token = this->advance_token();
      if (token->is_identifier())
	{
	  name = token->identifier();
	  if (name == "_")
	    {
	      go_error_at(this->location(), "invalid package name _");
	      name = Gogo::erroneous_name();
	    }
	  this->advance_token();
	}
      else
	{
	  go_error_at(this->location(), "package name must be an identifier");
	  name = "ERROR";
	}
    }
  this->gogo_->set_package_name(name, location);
}

// ImportDecl = "import" Decl<ImportSpec> .

void
Parse::import_decl()
{
  go_assert(this->peek_token()->is_keyword(KEYWORD_IMPORT));
  this->advance_token();
  this->decl(&Parse::import_spec, NULL);
}

// ImportSpec = [ "." | PackageName ] PackageFileName .

void
Parse::import_spec(void*)
{
  const Token* token = this->peek_token();
  Location location = token->location();

  std::string local_name;
  bool is_local_name_exported = false;
  if (token->is_op(OPERATOR_DOT))
    {
      local_name = ".";
      token = this->advance_token();
    }
  else if (token->is_identifier())
    {
      local_name = token->identifier();
      is_local_name_exported = token->is_identifier_exported();
      token = this->advance_token();
    }

  if (!token->is_string())
    {
      go_error_at(this->location(), "import statement not a string");
      this->advance_token();
      return;
    }

  this->gogo_->import_package(token->string_value(), local_name,
			      is_local_name_exported, true, location);

  this->advance_token();
}

// SourceFile       = PackageClause ";" { ImportDecl ";" }
//			{ TopLevelDecl ";" } .

void
Parse::program()
{
  this->package_clause();

  const Token* token = this->peek_token();
  if (token->is_op(OPERATOR_SEMICOLON))
    token = this->advance_token();
  else
    go_error_at(this->location(),
                "expected %<;%> or newline after package clause");

  while (token->is_keyword(KEYWORD_IMPORT))
    {
      this->import_decl();
      token = this->peek_token();
      if (token->is_op(OPERATOR_SEMICOLON))
	token = this->advance_token();
      else
	go_error_at(this->location(),
                    "expected %<;%> or newline after import declaration");
    }

  while (!token->is_eof())
    {
      if (this->declaration_may_start_here())
	this->declaration();
      else
	{
	  go_error_at(this->location(), "expected declaration");
	  this->gogo_->mark_locals_used();
	  do
	    this->advance_token();
	  while (!this->peek_token()->is_eof()
		 && !this->peek_token()->is_op(OPERATOR_SEMICOLON)
		 && !this->peek_token()->is_op(OPERATOR_RCURLY));
	  if (!this->peek_token()->is_eof()
	      && !this->peek_token()->is_op(OPERATOR_SEMICOLON))
	    this->advance_token();
	}
      token = this->peek_token();
      if (token->is_op(OPERATOR_SEMICOLON))
	token = this->advance_token();
      else if (!token->is_eof() || !saw_errors())
	{
	  if (token->is_op(OPERATOR_CHANOP))
	    go_error_at(this->location(),
                        ("send statement used as value; "
                         "use select for non-blocking send"));
	  else
	    go_error_at(this->location(),
                        ("expected %<;%> or newline after top "
                         "level declaration"));
	  this->skip_past_error(OPERATOR_INVALID);
	}
    }
}

// Reset the current iota value.

void
Parse::reset_iota()
{
  this->iota_ = 0;
}

// Return the current iota value.

int
Parse::iota_value()
{
  return this->iota_;
}

// Increment the current iota value.

void
Parse::increment_iota()
{
  ++this->iota_;
}

// Skip forward to a semicolon or OP.  OP will normally be
// OPERATOR_RPAREN or OPERATOR_RCURLY.  If we find a semicolon, move
// past it and return.  If we find OP, it will be the next token to
// read.  Return true if we are OK, false if we found EOF.

bool
Parse::skip_past_error(Operator op)
{
  this->gogo_->mark_locals_used();
  const Token* token = this->peek_token();
  while (!token->is_op(op))
    {
      if (token->is_eof())
	return false;
      if (token->is_op(OPERATOR_SEMICOLON))
	{
	  this->advance_token();
	  return true;
	}
      token = this->advance_token();
    }
  return true;
}

// Check that an expression is not a sink.

Expression*
Parse::verify_not_sink(Expression* expr)
{
  if (expr->is_sink_expression())
    {
      go_error_at(expr->location(), "cannot use _ as value");
      expr = Expression::make_error(expr->location());
    }

  // If this can not be a sink, and it is a variable, then we are
  // using the variable, not just assigning to it.
  if (expr->var_expression() != NULL)
    this->mark_var_used(expr->var_expression()->named_object());
  else if (expr->enclosed_var_expression() != NULL)
    this->mark_var_used(expr->enclosed_var_expression()->variable());
  return expr;
}

// Mark a variable as used.

void
Parse::mark_var_used(Named_object* no)
{
  if (no->is_variable())
    no->var_value()->set_is_used();
}
