// 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) const
{
  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),
    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 id_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,
							 id_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, id_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();
	      id_location = this->peek_token()->location();
	      id_name = this->gogo_->pack_hidden_name(name, is_exported);
	      ret->push_back(Typed_identifier(id_name, NULL, id_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,
							     id_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, "mixed named and unnamed function parameters");
      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)
      && !token->is_keyword(KEYWORD_TYPE))
    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(pragmas);
  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*, unsigned int), void* varg,
	    unsigned int pragmas)
{
  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, pragmas);
  else
    {
      if (pragmas != 0)
	go_warning_at(this->location(), 0,
		      "ignoring magic %<//go:...%> comment before group");
      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*, unsigned int), void* varg,
	    bool follow_is_paren)
{
  (this->*pfn)(varg, 0);
  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, 0);
    }
}

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

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

  int iota = 0;
  Type* last_type = NULL;
  Expression_list* last_expr_list = NULL;

  if (!this->peek_token()->is_op(OPERATOR_LPAREN))
    this->const_spec(iota, &last_type, &last_expr_list);
  else
    {
      this->advance_token();
      while (!this->peek_token()->is_op(OPERATOR_RPAREN))
	{
	  this->const_spec(iota, &last_type, &last_expr_list);
	  ++iota;
	  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(int iota, Type** last_type, Expression_list** last_expr_list)
{
  Location loc = this->location();
  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)
	{
	  Expression* copy = (*p)->copy();
	  copy->set_location(loc);
	  expr_list->push_back(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, iota);
      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, iota);
	  no->const_value()->set_is_sink();
	}
    }
  if (pe != expr_list->end())
    go_error_at(this->location(), "too many initializers");

  return;
}

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

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

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

void
Parse::type_spec(void*, unsigned int pragmas)
{
  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();
    }

  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);

	  if ((pragmas & GOPRAGMA_NOTINHEAP) != 0)
	    {
	      nt->set_not_in_heap();
	      pragmas &= ~GOPRAGMA_NOTINHEAP;
	    }
	  if (pragmas != 0)
	    go_warning_at(location, 0,
			  "ignoring magic %<//go:...%> comment before type");
	}
      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, 0);
}

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

void
Parse::var_spec(void*, unsigned int pragmas)
{
  if (pragmas != 0)
    go_warning_at(this->location(), 0,
		  "ignoring magic %<//go:...%> comment before var");

  // 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);
  var->set_is_global_sink();
  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))
		    {
		      // Use %s to print := to avoid -Wformat-diag warning.
		      go_error_at(id_location,
				  "%qs repeated on left side of %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, false));

	  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())
    {
      // Use %s to print := to avoid -Wformat-diag warning.
      go_error_at(dup_loc, "%qs repeated on left side of %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_YESWRITEBARRIERREC, "yeswritebarrierrec", 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, MPFR_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_dereference(closure_ref,
                                   Expression::NIL_CHECK_NOT_NEEDED,
                                   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_dereference(e, Expression::NIL_CHECK_NOT_NEEDED,
                                   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 id_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),
					   id_location, false, true);
	      is_name = true;
	    }
	  else
	    {
	      this->unget_token(Token::make_identifier_token(identifier,
							     is_exported,
							     id_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;

	  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 edepth = 0;
	  while (!token->is_eof()
		 && (edepth > 0 || !token->is_op(OPERATOR_RCURLY)))
	    {
	      if (token->is_op(OPERATOR_LCURLY))
		++edepth;
	      else if (token->is_op(OPERATOR_RCURLY))
		--edepth;
	      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);
  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, bool is_composite_literal_key)
{
  Named_object* in_function;
  Named_object* named_object = this->gogo_->lookup(name, &in_function);
  if (named_object == NULL)
    {
      if (is_composite_literal_key)
	{
	  // This is a composite literal key, which means that it
	  // could just be a struct field name, so avoid confusiong by
	  // not adding it to the bindings.  We'll look up the name
	  // later during the lowering phase if necessary.
	  return Expression::make_composite_literal_key(name, location);
	}
      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);
      call_expr->set_is_concurrent();
    }
  else
    {
      stat = Statement::make_defer_statement(call_expr, stat_location);
      call_expr->set_is_deferred();
    }
  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, "unexpected semicolon or newline, expecting %<{%> 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;
      while (this->advance_token()->is_op(OPERATOR_SEMICOLON))
	;
      if (this->peek_token()->is_op(OPERATOR_RCURLY))
	go_error_at(fallthrough_loc,
		    _("cannot fallthrough final case in switch"));
      else if (!this->peek_token()->is_keyword(KEYWORD_CASE)
	       && !this->peek_token()->is_keyword(KEYWORD_DEFAULT))
	{
	  go_error_at(fallthrough_loc, "fallthrough statement out of place");
	  while (!this->peek_token()->is_keyword(KEYWORD_CASE)
		 && !this->peek_token()->is_keyword(KEYWORD_DEFAULT)
		 && !this->peek_token()->is_op(OPERATOR_RCURLY)
		 && !this->peek_token()->is_eof())
	    {
	      if (this->statement_may_start_here())
		this->statement_list();
	      else
		this->advance_token();
	    }
	}
    }

  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 but 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, false);
	  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);
      if (e->receive_expression() != NULL)
	{
	  *is_send = false;
	  *channel = e->receive_expression()->channel();
	  // This is 'case (<-c):'.  We now expect ':'.  If we see
	  // '<-', then we have case (<-c)<-v:
	  if (!this->peek_token()->is_op(OPERATOR_CHANOP))
	    return true;
	}
    }
  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))
    {
      *is_send = false;
      this->advance_token();
      Location recvloc = this->location();
      Expression* recvexpr = this->expression(PRECEDENCE_NORMAL, false,
					      true, NULL, NULL);
      if (recvexpr->receive_expression() == NULL)
	{
	  go_error_at(recvloc, "missing %<<-%>");
	  return false;
	}
      *channel = recvexpr->receive_expression()->channel();
      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, "unexpected semicolon or newline, expecting %<{%> 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(), "unexpected semicolon or newline, expecting %<{%> 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;
      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, 0);
}

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

void
Parse::import_spec(void*, unsigned int pragmas)
{
  if (pragmas != 0)
    go_warning_at(this->location(), 0,
		  "ignoring magic %<//go:...%> comment before import");

  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 path must be 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);
	}
    }
}

// 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();
}
