LCOV - code coverage report
Current view: top level - gcc/go/gofrontend - statements.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.8 % 3715 3186
Test Date: 2026-02-28 14:20:25 Functions: 84.4 % 295 249
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // statements.cc -- Go frontend statements.
       2              : 
       3              : // Copyright 2009 The Go Authors. All rights reserved.
       4              : // Use of this source code is governed by a BSD-style
       5              : // license that can be found in the LICENSE file.
       6              : 
       7              : #include "go-system.h"
       8              : 
       9              : #include "go-c.h"
      10              : #include "go-diagnostics.h"
      11              : #include "types.h"
      12              : #include "expressions.h"
      13              : #include "gogo.h"
      14              : #include "export.h"
      15              : #include "import.h"
      16              : #include "runtime.h"
      17              : #include "backend.h"
      18              : #include "statements.h"
      19              : #include "ast-dump.h"
      20              : 
      21              : // Class Statement.
      22              : 
      23      7691188 : Statement::Statement(Statement_classification classification,
      24      7691188 :                      Location location)
      25      7691188 :   : classification_(classification), location_(location)
      26              : {
      27      7691188 : }
      28              : 
      29            0 : Statement::~Statement()
      30              : {
      31            0 : }
      32              : 
      33              : // Traverse the tree.  The work of walking the components is handled
      34              : // by the subclasses.
      35              : 
      36              : int
      37     93723028 : Statement::traverse(Block* block, size_t* pindex, Traverse* traverse)
      38              : {
      39     93723028 :   if (this->classification_ == STATEMENT_ERROR)
      40              :     return TRAVERSE_CONTINUE;
      41              : 
      42     93720219 :   unsigned int traverse_mask = traverse->traverse_mask();
      43              : 
      44     93720219 :   if ((traverse_mask & Traverse::traverse_statements) != 0)
      45              :     {
      46     56917113 :       int t = traverse->statement(block, pindex, this);
      47     56917113 :       if (t == TRAVERSE_EXIT)
      48              :         return TRAVERSE_EXIT;
      49     56897926 :       else if (t == TRAVERSE_SKIP_COMPONENTS)
      50              :         return TRAVERSE_CONTINUE;
      51              :     }
      52              : 
      53              :   // No point in checking traverse_mask here--a statement may contain
      54              :   // other blocks or statements, and if we got here we always want to
      55              :   // walk them.
      56     79650773 :   return this->do_traverse(traverse);
      57              : }
      58              : 
      59              : // Traverse the contents of a statement.
      60              : 
      61              : int
      62     24055790 : Statement::traverse_contents(Traverse* traverse)
      63              : {
      64     24055790 :   return this->do_traverse(traverse);
      65              : }
      66              : 
      67              : // Traverse an expression in a statement.  This is a helper function
      68              : // for child classes.
      69              : 
      70              : int
      71     70848662 : Statement::traverse_expression(Traverse* traverse, Expression** expr)
      72              : {
      73     70848662 :   if ((traverse->traverse_mask()
      74     70848662 :        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
      75              :     return TRAVERSE_CONTINUE;
      76     51025910 :   return Expression::traverse(expr, traverse);
      77              : }
      78              : 
      79              : // Traverse an expression list in a statement.  This is a helper
      80              : // function for child classes.
      81              : 
      82              : int
      83      7563434 : Statement::traverse_expression_list(Traverse* traverse,
      84              :                                     Expression_list* expr_list)
      85              : {
      86      7563434 :   if (expr_list == NULL)
      87              :     return TRAVERSE_CONTINUE;
      88      1522244 :   if ((traverse->traverse_mask()
      89      1522244 :        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
      90              :     return TRAVERSE_CONTINUE;
      91      1522244 :   return expr_list->traverse(traverse);
      92              : }
      93              : 
      94              : // Traverse a type in a statement.  This is a helper function for
      95              : // child classes.
      96              : 
      97              : int
      98     11450829 : Statement::traverse_type(Traverse* traverse, Type* type)
      99              : {
     100     11450829 :   if ((traverse->traverse_mask()
     101     11450829 :        & (Traverse::traverse_types | Traverse::traverse_expressions)) == 0)
     102              :     return TRAVERSE_CONTINUE;
     103      8076536 :   return Type::traverse(type, traverse);
     104              : }
     105              : 
     106              : // Set type information for unnamed constants.  This is really done by
     107              : // the child class.
     108              : 
     109              : void
     110      5804307 : Statement::determine_types(Gogo* gogo)
     111              : {
     112      5804307 :   this->do_determine_types(gogo);
     113      5804307 : }
     114              : 
     115              : // Read a statement from export data.
     116              : 
     117              : Statement*
     118        69326 : Statement::import_statement(Import_function_body* ifb, Location loc)
     119              : {
     120        69326 :   if (ifb->match_c_string("{"))
     121              :     {
     122        21059 :       bool is_lowered_for_statement;
     123        21059 :       Block* block = Block_statement::do_import(ifb, loc,
     124              :                                                 &is_lowered_for_statement);
     125        21059 :       if (block == NULL)
     126            0 :         return Statement::make_error_statement(loc);
     127        21059 :       Block_statement* s = Statement::make_block_statement(block, loc);
     128        21059 :       if (is_lowered_for_statement)
     129            0 :         s->set_is_lowered_for_statement();
     130        21059 :       return s;
     131              :     }
     132        48267 :   else if (ifb->match_c_string("return"))
     133              :     {
     134              :       // After lowering return statements have no expressions.  The
     135              :       // return expressions are assigned to result parameters.
     136        12579 :       ifb->advance(6);
     137        12579 :       return Statement::make_return_statement(ifb->function(), NULL, loc);
     138              :     }
     139        35688 :   else if (ifb->match_c_string("var $t"))
     140         2661 :     return Temporary_statement::do_import(ifb, loc);
     141        33027 :   else if (ifb->match_c_string("var "))
     142         3280 :     return Variable_declaration_statement::do_import(ifb, loc);
     143        29747 :   else if (ifb->match_c_string("if "))
     144         5427 :     return If_statement::do_import(ifb, loc);
     145        24320 :   else if (ifb->match_c_string(":"))
     146         1434 :     return Label_statement::do_import(ifb, loc);
     147        22886 :   else if (ifb->match_c_string("goto "))
     148         1523 :     return Goto_statement::do_import(ifb, loc);
     149              : 
     150        21363 :   Expression* lhs = Expression::import_expression(ifb, loc);
     151              : 
     152        21363 :   if (ifb->match_c_string(" //"))
     153         4246 :     return Statement::make_statement(lhs, true);
     154              : 
     155        17117 :   ifb->require_c_string(" = ");
     156        17117 :   Expression* rhs = Expression::import_expression(ifb, loc);
     157        17117 :   return Statement::make_assignment(lhs, rhs, loc);
     158              : }
     159              : 
     160              : // If this is a thunk statement, return it.
     161              : 
     162              : Thunk_statement*
     163      2146944 : Statement::thunk_statement()
     164              : {
     165      2146944 :   Thunk_statement* ret = this->convert<Thunk_statement, STATEMENT_GO>();
     166      2141907 :   if (ret == NULL)
     167      2141907 :     ret = this->convert<Thunk_statement, STATEMENT_DEFER>();
     168      2146944 :   return ret;
     169              : }
     170              : 
     171              : // Convert a Statement to the backend representation.  This is really
     172              : // done by the child class.
     173              : 
     174              : Bstatement*
     175      7173369 : Statement::get_backend(Translate_context* context)
     176              : {
     177      7173369 :   if (this->classification_ == STATEMENT_ERROR)
     178          580 :     return context->backend()->error_statement();
     179      7172789 :   return this->do_get_backend(context);
     180              : }
     181              : 
     182              : // Dump AST representation for a statement to a dump context.
     183              : 
     184              : void
     185            0 : Statement::dump_statement(Ast_dump_context* ast_dump_context) const
     186              : {
     187            0 :   this->do_dump_statement(ast_dump_context);
     188            0 : }
     189              : 
     190              : // Note that this statement is erroneous.  This is called by children
     191              : // when they discover an error.
     192              : 
     193              : void
     194          284 : Statement::set_is_error()
     195              : {
     196          284 :   this->classification_ = STATEMENT_ERROR;
     197          284 : }
     198              : 
     199              : // For children to call to report an error conveniently.
     200              : 
     201              : void
     202           28 : Statement::report_error(const char* msg)
     203              : {
     204           28 :   go_error_at(this->location_, "%s", msg);
     205           28 :   this->set_is_error();
     206           28 : }
     207              : 
     208              : // An error statement, used to avoid crashing after we report an
     209              : // error.
     210              : 
     211              : class Error_statement : public Statement
     212              : {
     213              :  public:
     214          362 :   Error_statement(Location location)
     215          724 :     : Statement(STATEMENT_ERROR, location)
     216              :   { }
     217              : 
     218              :  protected:
     219              :   int
     220          362 :   do_traverse(Traverse*)
     221          362 :   { return TRAVERSE_CONTINUE; }
     222              : 
     223              :   Bstatement*
     224            0 :   do_get_backend(Translate_context*)
     225            0 :   { go_unreachable(); }
     226              : 
     227              :   void
     228              :   do_dump_statement(Ast_dump_context*) const;
     229              : };
     230              : 
     231              : //
     232              : // Helper to tack on available source position information
     233              : // at the end of a statement.
     234              : //
     235              : static std::string
     236            0 : dsuffix(Location location)
     237              : {
     238            0 :   std::string lstr = Linemap::location_to_string(location);
     239            0 :   if (lstr == "")
     240            0 :     return lstr;
     241            0 :   std::string rval(" // ");
     242            0 :   rval += lstr;
     243            0 :   return rval;
     244            0 : }
     245              : 
     246              : // Dump the AST representation for an error statement.
     247              : 
     248              : void
     249            0 : Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
     250              : {
     251            0 :   ast_dump_context->print_indent();
     252            0 :   ast_dump_context->ostream() << "Error statement" << std::endl;
     253            0 : }
     254              : 
     255              : // Make an error statement.
     256              : 
     257              : Statement*
     258          362 : Statement::make_error_statement(Location location)
     259              : {
     260          362 :   return new Error_statement(location);
     261              : }
     262              : 
     263              : // Class Variable_declaration_statement.
     264              : 
     265       383755 : Variable_declaration_statement::Variable_declaration_statement(
     266       383755 :     Named_object* var)
     267              :   : Statement(STATEMENT_VARIABLE_DECLARATION, var->var_value()->location()),
     268       383755 :     var_(var)
     269              : {
     270       383755 : }
     271              : 
     272              : // We don't actually traverse the variable here; it was traversed
     273              : // while traversing the Block.
     274              : 
     275              : int
     276      8686700 : Variable_declaration_statement::do_traverse(Traverse*)
     277              : {
     278      8686700 :   return TRAVERSE_CONTINUE;
     279              : }
     280              : 
     281              : void
     282       419772 : Variable_declaration_statement::do_determine_types(Gogo* gogo)
     283              : {
     284       419772 :   this->var_->var_value()->determine_type(gogo);
     285       419772 : }
     286              : 
     287              : // Lower the variable's initialization expression.
     288              : 
     289              : Statement*
     290       538538 : Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function,
     291              :                                          Block*, Statement_inserter* inserter)
     292              : {
     293       538538 :   this->var_->var_value()->lower_init_expression(gogo, function, inserter);
     294       538538 :   return this;
     295              : }
     296              : 
     297              : // Flatten the variable's initialization expression.
     298              : 
     299              : Statement*
     300       402409 : Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function,
     301              :                                            Block*, Statement_inserter* inserter)
     302              : {
     303       402409 :   Variable* var = this->var_->var_value();
     304       402409 :   if (var->type()->is_error_type()
     305       402409 :       || (var->init() != NULL
     306       288428 :           && var->init()->is_error_expression()))
     307              :     {
     308           57 :       go_assert(saw_errors());
     309           57 :       return Statement::make_error_statement(this->location());
     310              :     }
     311       402352 :   this->var_->var_value()->flatten_init_expression(gogo, function, inserter);
     312       402352 :   return this;
     313              : }
     314              : 
     315              : // Add explicit type conversions.
     316              : 
     317              : void
     318       382630 : Variable_declaration_statement::do_add_conversions()
     319              : {
     320       382630 :   Variable* var = this->var_->var_value();
     321       382630 :   Expression* init = var->init();
     322       382630 :   if (init == NULL)
     323              :     return;
     324       280746 :   Type* lt = var->type();
     325       280746 :   Type* rt = init->type();
     326       280746 :   if (!Type::are_identical(lt, rt, 0, NULL)
     327       280746 :       && lt->interface_type() != NULL)
     328          341 :     var->set_init(Expression::make_cast(lt, init, this->location()));
     329              : }
     330              : 
     331              : // Convert a variable declaration to the backend representation.
     332              : 
     333              : Bstatement*
     334       382456 : Variable_declaration_statement::do_get_backend(Translate_context* context)
     335              : {
     336       382456 :   if (this->var_->is_redefinition())
     337            2 :     return context->backend()->error_statement();
     338       382454 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
     339       382454 :   Variable* var = this->var_->var_value();
     340       382454 :   Bvariable* bvar = this->var_->get_backend_variable(context->gogo(),
     341              :                                                      context->function());
     342       382454 :   Bexpression* binit = var->get_init(context->gogo(), context->function());
     343              : 
     344       382454 :   if (!var->is_in_heap())
     345              :     {
     346       368506 :       go_assert(binit != NULL);
     347       368506 :       return context->backend()->init_statement(bfunction, bvar, binit);
     348              :     }
     349              : 
     350              :   // Something takes the address of this variable, so the value is
     351              :   // stored in the heap.  Initialize it to newly allocated memory
     352              :   // space, and assign the initial value to the new space.
     353        13948 :   Location loc = this->location();
     354        13948 :   Named_object* newfn = context->gogo()->lookup_global("new");
     355        13948 :   go_assert(newfn != NULL && newfn->is_function_declaration());
     356        13948 :   Expression* func = Expression::make_func_reference(newfn, NULL, loc);
     357        13948 :   Expression_list* params = new Expression_list();
     358        13948 :   params->push_back(Expression::make_type(var->type(), loc));
     359        13948 :   Expression* call = Expression::make_call(func, params, false, loc);
     360        13948 :   context->gogo()->lower_expression(context->function(), NULL, &call);
     361        13948 :   Temporary_statement* temp = Statement::make_temporary(NULL, call, loc);
     362        13948 :   Bstatement* btemp = temp->get_backend(context);
     363              : 
     364        13948 :   Bstatement* set = NULL;
     365        13948 :   if (binit != NULL)
     366              :     {
     367         1189 :       Expression* e = Expression::make_temporary_reference(temp, loc);
     368         1189 :       e = Expression::make_dereference(e, Expression::NIL_CHECK_NOT_NEEDED,
     369              :                                        loc);
     370         1189 :       Bexpression* be = e->get_backend(context);
     371         1189 :       set = context->backend()->assignment_statement(bfunction, be, binit, loc);
     372              :     }
     373              : 
     374        13948 :   Expression* ref = Expression::make_temporary_reference(temp, loc);
     375        13948 :   Bexpression* bref = ref->get_backend(context);
     376        13948 :   Bstatement* sinit = context->backend()->init_statement(bfunction, bvar, bref);
     377              : 
     378        13948 :   std::vector<Bstatement*> stats;
     379        13948 :   stats.reserve(3);
     380        13948 :   stats.push_back(btemp);
     381        13948 :   if (set != NULL)
     382         1189 :     stats.push_back(set);
     383        13948 :   stats.push_back(sinit);
     384        13948 :   return context->backend()->statement_list(stats);
     385        13948 : }
     386              : 
     387              : // Dump the AST representation for a variable declaration.
     388              : 
     389              : void
     390            0 : Variable_declaration_statement::do_dump_statement(
     391              :     Ast_dump_context* ast_dump_context) const
     392              : {
     393            0 :   ast_dump_context->print_indent();
     394              : 
     395            0 :   go_assert(var_->is_variable());
     396            0 :   ast_dump_context->ostream() << "var " << this->var_->name() <<  " ";
     397            0 :   Variable* var = this->var_->var_value();
     398            0 :   if (var->has_type())
     399              :     {
     400            0 :       ast_dump_context->dump_type(var->type());
     401            0 :       ast_dump_context->ostream() << " ";
     402              :     }
     403            0 :   if (var->init() != NULL)
     404              :     {
     405            0 :       ast_dump_context->ostream() <<  "= ";
     406            0 :       ast_dump_context->dump_expression(var->init());
     407              :     }
     408            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
     409            0 : }
     410              : 
     411              : // Make a variable declaration.
     412              : 
     413              : Statement*
     414       383755 : Statement::make_variable_declaration(Named_object* var)
     415              : {
     416       383755 :   return new Variable_declaration_statement(var);
     417              : }
     418              : 
     419              : // Export a variable declaration.
     420              : 
     421              : void
     422         4064 : Variable_declaration_statement::do_export_statement(Export_function_body* efb)
     423              : {
     424         4064 :   efb->write_c_string("var ");
     425         4064 :   efb->write_string(Gogo::unpack_hidden_name(this->var_->name()));
     426         4064 :   efb->write_c_string(" ");
     427         4064 :   Variable* var = this->var_->var_value();
     428         4064 :   Type* type = var->type();
     429         4064 :   efb->write_type(type);
     430         4064 :   Expression* init = var->init();
     431         4064 :   if (init != NULL)
     432              :     {
     433         2885 :       efb->write_c_string(" = ");
     434              : 
     435         2885 :       go_assert(efb->type_context() == NULL);
     436         2885 :       efb->set_type_context(type);
     437              : 
     438         2885 :       init->export_expression(efb);
     439              : 
     440         2885 :       efb->set_type_context(NULL);
     441              :     }
     442         4064 : }
     443              : 
     444              : // Import a variable declaration.
     445              : 
     446              : Statement*
     447         3280 : Variable_declaration_statement::do_import(Import_function_body* ifb,
     448              :                                           Location loc)
     449              : {
     450         3280 :   ifb->require_c_string("var ");
     451         3280 :   std::string id = ifb->read_identifier();
     452         3280 :   ifb->require_c_string(" ");
     453         3280 :   Type* type = ifb->read_type();
     454         3280 :   Expression* init = NULL;
     455         3280 :   if (ifb->match_c_string(" = "))
     456              :     {
     457         2682 :       ifb->advance(3);
     458         2682 :       init = Expression::import_expression(ifb, loc);
     459              :     }
     460         3280 :   Variable* var = new Variable(type, init, false, false, false, loc);
     461         3280 :   var->set_is_used();
     462              :   // FIXME: The package we are importing does not yet exist, so we
     463              :   // can't pass the correct package here.  It probably doesn't matter.
     464         3280 :   Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var);
     465         3280 :   return Statement::make_variable_declaration(no);
     466         3280 : }
     467              : 
     468              : // Class Temporary_statement.
     469              : 
     470              : // Return the type of the temporary variable.
     471              : 
     472              : Type*
     473     27299919 : Temporary_statement::type() const
     474              : {
     475     27299919 :   Type* type = this->type_ != NULL ? this->type_ : this->init_->type();
     476              : 
     477              :   // Temporary variables cannot have a void type.
     478     27299919 :   if (type->is_void_type())
     479              :     {
     480            0 :       go_assert(saw_errors());
     481            0 :       return Type::make_error_type();
     482              :     }
     483              :   return type;
     484              : }
     485              : 
     486              : // Traversal.
     487              : 
     488              : int
     489     17308805 : Temporary_statement::do_traverse(Traverse* traverse)
     490              : {
     491     17308805 :   if (this->type_ != NULL
     492     17308805 :       && this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
     493              :     return TRAVERSE_EXIT;
     494     17308805 :   if (this->init_ == NULL)
     495              :     return TRAVERSE_CONTINUE;
     496              :   else
     497     13618364 :     return this->traverse_expression(traverse, &this->init_);
     498              : }
     499              : 
     500              : // Determine types.
     501              : 
     502              : void
     503       656614 : Temporary_statement::do_determine_types(Gogo* gogo)
     504              : {
     505       656614 :   if (this->type_ != NULL && this->type_->is_abstract())
     506          970 :     this->type_ = this->type_->make_non_abstract_type();
     507              : 
     508       656614 :   if (this->init_ != NULL)
     509              :     {
     510       613556 :       if (this->type_ == NULL)
     511       363877 :         this->init_->determine_type_no_context(gogo);
     512              :       else
     513              :         {
     514       249679 :           Type_context context(this->type_, false);
     515       249679 :           this->init_->determine_type(gogo, &context);
     516              :         }
     517              :     }
     518              : 
     519       656614 :   if (this->type_ == NULL)
     520              :     {
     521       363877 :       this->type_ = this->init_->type();
     522       363877 :       go_assert(!this->type_->is_abstract());
     523              :     }
     524       656614 : }
     525              : 
     526              : // Check types.
     527              : 
     528              : void
     529         6221 : Temporary_statement::do_check_types(Gogo*)
     530              : {
     531         6221 :   if (this->type_ != NULL && this->init_ != NULL)
     532              :     {
     533         2012 :       std::string reason;
     534         2012 :       if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
     535              :         {
     536            0 :           if (reason.empty())
     537            0 :             go_error_at(this->location(), "incompatible types in assignment");
     538              :           else
     539            0 :             go_error_at(this->location(), "incompatible types in assignment (%s)",
     540              :                      reason.c_str());
     541            0 :           this->set_is_error();
     542              :         }
     543         2012 :     }
     544         6221 : }
     545              : 
     546              : // Flatten a temporary statement: add another temporary when it might
     547              : // be needed for interface conversion.
     548              : 
     549              : Statement*
     550      1464241 : Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
     551              :                                 Statement_inserter* inserter)
     552              : {
     553      1464241 :   if (this->type()->is_error_type()
     554      1464241 :       || (this->init_ != NULL
     555      1252625 :           && this->init_->is_error_expression()))
     556              :     {
     557           35 :       go_assert(saw_errors());
     558           35 :       return Statement::make_error_statement(this->location());
     559              :     }
     560              : 
     561      1464206 :   if (this->type_ != NULL
     562       823513 :       && this->init_ != NULL
     563       611932 :       && !Type::are_identical(this->type_, this->init_->type(),
     564              :                               Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
     565              :                               NULL)
     566        18581 :       && this->init_->type()->interface_type() != NULL
     567      1464206 :       && !this->init_->is_multi_eval_safe())
     568              :     {
     569            0 :       Temporary_statement *temp =
     570            0 :         Statement::make_temporary(NULL, this->init_, this->location());
     571            0 :       inserter->insert(temp);
     572            0 :       this->init_ = Expression::make_temporary_reference(temp,
     573              :                                                          this->location());
     574              :     }
     575      1464206 :   return this;
     576              : }
     577              : 
     578              : // Add explicit type conversions.
     579              : 
     580              : void
     581       514598 : Temporary_statement::do_add_conversions()
     582              : {
     583       514598 :   if (this->init_ == NULL)
     584              :     return;
     585       342879 :   Type* lt = this->type();
     586       342879 :   Type* rt = this->init_->type();
     587       342879 :   if (!Type::are_identical(lt, rt, 0, NULL)
     588       342879 :       && lt->interface_type() != NULL)
     589        20988 :     this->init_ = Expression::make_cast(lt, this->init_, this->location());
     590              : }
     591              : 
     592              : // Convert to backend representation.
     593              : 
     594              : Bstatement*
     595      1904105 : Temporary_statement::do_get_backend(Translate_context* context)
     596              : {
     597      1904105 :   go_assert(this->bvariable_ == NULL);
     598              : 
     599      1904105 :   Named_object* function = context->function();
     600      1904105 :   go_assert(function != NULL);
     601      1904105 :   Bfunction* bfunction = function->func_value()->get_decl();
     602      1904105 :   Btype* btype = this->type()->get_backend(context->gogo());
     603              : 
     604      1904105 :   Bexpression* binit;
     605      1904105 :   if (this->init_ == NULL)
     606              :     binit = NULL;
     607      1693091 :   else if (this->type_ == NULL)
     608       832737 :     binit = this->init_->get_backend(context);
     609              :   else
     610              :     {
     611       860354 :       Expression* init = Expression::convert_for_assignment(context->gogo(),
     612              :                                                             this->type_,
     613              :                                                             this->init_,
     614              :                                                             this->location());
     615       860354 :       binit = init->get_backend(context);
     616              :     }
     617              : 
     618      1693091 :   if (binit != NULL)
     619      1693091 :     binit = context->backend()->convert_expression(btype, binit,
     620              :                                                    this->location());
     621              : 
     622      1904105 :   unsigned int flags = 0;
     623      1904105 :   if (this->is_address_taken_)
     624        43829 :     flags |= Backend::variable_address_is_taken;
     625      1904105 :   Bstatement* statement;
     626      1904105 :   this->bvariable_ =
     627      1904105 :     context->backend()->temporary_variable(bfunction, context->bblock(),
     628              :                                            btype, binit, flags,
     629              :                                            this->location(), &statement);
     630      1904105 :   return statement;
     631              : }
     632              : 
     633              : // Return the backend variable.
     634              : 
     635              : Bvariable*
     636      3817044 : Temporary_statement::get_backend_variable(Translate_context* context) const
     637              : {
     638      3817044 :   if (this->bvariable_ == NULL)
     639              :     {
     640            0 :       go_assert(saw_errors());
     641            0 :       return context->backend()->error_variable();
     642              :     }
     643              :   return this->bvariable_;
     644              : }
     645              : 
     646              : // Dump the AST represemtation for a temporary statement
     647              : 
     648              : void
     649            0 : Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
     650              : {
     651            0 :   ast_dump_context->print_indent();
     652            0 :   ast_dump_context->dump_temp_variable_name(this);
     653            0 :   if (this->type_ != NULL)
     654              :     {
     655            0 :       ast_dump_context->ostream() << " ";
     656            0 :       ast_dump_context->dump_type(this->type_);
     657              :     }
     658            0 :   if (this->init_ != NULL)
     659              :     {
     660            0 :       ast_dump_context->ostream() << " = ";
     661            0 :       ast_dump_context->dump_expression(this->init_);
     662              :     }
     663            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
     664            0 : }
     665              : 
     666              : // Make and initialize a temporary variable in BLOCK.
     667              : 
     668              : Temporary_statement*
     669      1907448 : Statement::make_temporary(Type* type, Expression* init,
     670              :                           Location location)
     671              : {
     672      1907448 :   return new Temporary_statement(type, init, location);
     673              : }
     674              : 
     675              : // Export a temporary statement.
     676              : 
     677              : void
     678         4501 : Temporary_statement::do_export_statement(Export_function_body* efb)
     679              : {
     680         4501 :   unsigned int idx = efb->record_temporary(this);
     681         4501 :   char buf[100];
     682         4501 :   snprintf(buf, sizeof buf, "var $t%u", idx);
     683         4501 :   efb->write_c_string(buf);
     684         4501 :   if (this->type_ != NULL)
     685              :     {
     686         3641 :       efb->write_c_string(" ");
     687         3641 :       efb->write_type(this->type_);
     688              :     }
     689         4501 :   if (this->init_ != NULL)
     690              :     {
     691         3924 :       efb->write_c_string(" = ");
     692              : 
     693         3924 :       go_assert(efb->type_context() == NULL);
     694         3924 :       efb->set_type_context(this->type_);
     695              : 
     696         3924 :       this->init_->export_expression(efb);
     697              : 
     698         3924 :       efb->set_type_context(NULL);
     699              :     }
     700         4501 : }
     701              : 
     702              : // Import a temporary statement.
     703              : 
     704              : Statement*
     705         2661 : Temporary_statement::do_import(Import_function_body* ifb, Location loc)
     706              : {
     707         2661 :   ifb->require_c_string("var ");
     708         2661 :   std::string id = ifb->read_identifier();
     709         2661 :   go_assert(id[0] == '$' && id[1] == 't');
     710         2661 :   const char *p = id.c_str();
     711         2661 :   char *end;
     712         2661 :   long idx = strtol(p + 2, &end, 10);
     713         2661 :   if (*end != '\0' || idx > 0x7fffffff)
     714              :     {
     715            0 :       if (!ifb->saw_error())
     716            0 :         go_error_at(loc,
     717              :                     ("invalid export data for %qs: "
     718              :                      "bad temporary statement index at %lu"),
     719            0 :                     ifb->name().c_str(),
     720            0 :                     static_cast<unsigned long>(ifb->off()));
     721            0 :       ifb->set_saw_error();
     722            0 :       return Statement::make_error_statement(loc);
     723              :     }
     724              : 
     725         2661 :   Type* type = NULL;
     726         2661 :   if (!ifb->match_c_string(" = "))
     727              :     {
     728         2661 :       ifb->require_c_string(" ");
     729         2661 :       type = ifb->read_type();
     730              :     }
     731         2661 :   Expression* init = NULL;
     732         2661 :   if (ifb->match_c_string(" = "))
     733              :     {
     734         2309 :       ifb->advance(3);
     735         2309 :       init = Expression::import_expression(ifb, loc);
     736              :     }
     737         2661 :   if (type == NULL && init == NULL)
     738              :     {
     739            0 :       if (!ifb->saw_error())
     740            0 :         go_error_at(loc,
     741              :                     ("invalid export data for %qs: "
     742              :                      "temporary statement has neither type nor init at %lu"),
     743            0 :                     ifb->name().c_str(),
     744            0 :                     static_cast<unsigned long>(ifb->off()));
     745            0 :       ifb->set_saw_error();
     746              :       return Statement::make_error_statement(loc);
     747              :     }
     748              : 
     749         2661 :   Temporary_statement* temp = Statement::make_temporary(type, init, loc);
     750              : 
     751         2661 :   ifb->record_temporary(temp, static_cast<unsigned int>(idx));
     752              : 
     753         2661 :   return temp;
     754         2661 : }
     755              : 
     756              : // The Move_subexpressions class is used to move all top-level
     757              : // subexpressions of an expression.  This is used for things like
     758              : // index expressions in which we must evaluate the index value before
     759              : // it can be changed by a multiple assignment.
     760              : 
     761        16568 : class Move_subexpressions : public Traverse
     762              : {
     763              :  public:
     764        19017 :   Move_subexpressions(int skip, Block* block)
     765        19017 :     : Traverse(traverse_expressions),
     766        19017 :       skip_(skip), block_(block)
     767              :   { }
     768              : 
     769              :  protected:
     770              :   int
     771              :   expression(Expression**);
     772              : 
     773              :  private:
     774              :   // The number of subexpressions to skip moving.  This is used to
     775              :   // avoid moving the array itself, as we only need to move the index.
     776              :   int skip_;
     777              :   // The block where new temporary variables should be added.
     778              :   Block* block_;
     779              : };
     780              : 
     781              : int
     782        23414 : Move_subexpressions::expression(Expression** pexpr)
     783              : {
     784        23414 :   if (this->skip_ > 0)
     785         2017 :     --this->skip_;
     786        21397 :   else if ((*pexpr)->temporary_reference_expression() == NULL
     787        21103 :            && !(*pexpr)->is_nil_expression()
     788        21089 :            && !(*pexpr)->is_constant())
     789              :     {
     790        19685 :       Location loc = (*pexpr)->location();
     791        19685 :       Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
     792        19685 :       this->block_->add_statement(temp);
     793        19685 :       *pexpr = Expression::make_temporary_reference(temp, loc);
     794              :     }
     795              :   // We only need to move top-level subexpressions.
     796        23414 :   return TRAVERSE_SKIP_COMPONENTS;
     797              : }
     798              : 
     799              : // The Move_ordered_evals class is used to find any subexpressions of
     800              : // an expression that have an evaluation order dependency.  It creates
     801              : // temporary variables to hold them.
     802              : 
     803        84127 : class Move_ordered_evals : public Traverse
     804              : {
     805              :  public:
     806       202938 :   Move_ordered_evals(Block* block)
     807       202938 :     : Traverse(traverse_expressions),
     808       202938 :       block_(block)
     809              :   { }
     810              : 
     811              :  protected:
     812              :   int
     813              :   expression(Expression**);
     814              : 
     815              :  private:
     816              :   // The block where new temporary variables should be added.
     817              :   Block* block_;
     818              : };
     819              : 
     820              : int
     821       277244 : Move_ordered_evals::expression(Expression** pexpr)
     822              : {
     823              :   // We have to look at subexpressions first.
     824       277244 :   if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
     825              :     return TRAVERSE_EXIT;
     826              : 
     827       277244 :   int i;
     828       277244 :   if ((*pexpr)->must_eval_subexpressions_in_order(&i))
     829              :     {
     830        16568 :       Move_subexpressions ms(i, this->block_);
     831        16568 :       if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT)
     832            0 :         return TRAVERSE_EXIT;
     833        16568 :     }
     834              : 
     835       277244 :   if ((*pexpr)->must_eval_in_order())
     836              :     {
     837          667 :       Call_expression* call = (*pexpr)->call_expression();
     838          666 :       if (call != NULL && call->is_multi_value_arg())
     839              :         {
     840              :           // A call expression which returns multiple results as an argument
     841              :           // to another call must be handled specially.  We can't create a
     842              :           // temporary because there is no type to give it.  Instead, group
     843              :           // the caller and this multi-valued call argument and use a temporary
     844              :           // variable to hold them.
     845            0 :           return TRAVERSE_SKIP_COMPONENTS;
     846              :         }
     847              : 
     848          667 :       Location loc = (*pexpr)->location();
     849          667 :       Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
     850          667 :       this->block_->add_statement(temp);
     851          667 :       *pexpr = Expression::make_temporary_reference(temp, loc);
     852              :     }
     853              :   return TRAVERSE_SKIP_COMPONENTS;
     854              : }
     855              : 
     856              : // Class Assignment_statement.
     857              : 
     858              : // Traversal.
     859              : 
     860              : int
     861     18722813 : Assignment_statement::do_traverse(Traverse* traverse)
     862              : {
     863     18722813 :   if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
     864              :     return TRAVERSE_EXIT;
     865     18656969 :   return this->traverse_expression(traverse, &this->rhs_);
     866              : }
     867              : 
     868              : // Lower an assignment to a map index expression to a runtime function
     869              : // call.  Mark some slice assignments as not requiring a write barrier.
     870              : 
     871              : Statement*
     872      1388224 : Assignment_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
     873              :                                Statement_inserter*)
     874              : {
     875      1388224 :   Map_index_expression* mie = this->lhs_->map_index_expression();
     876      1388224 :   if (mie != NULL)
     877              :     {
     878         5656 :       Location loc = this->location();
     879              : 
     880         5656 :       Expression* map = mie->map();
     881         5656 :       Map_type* mt = map->type()->map_type();
     882         5656 :       if (mt == NULL)
     883              :         {
     884            0 :           go_assert(saw_errors());
     885            0 :           return Statement::make_error_statement(loc);
     886              :         }
     887              : 
     888         5656 :       Block* b = new Block(enclosing, loc);
     889              : 
     890              :       // Move out any subexpressions on the left hand side to make
     891              :       // sure that functions are called in the required order.
     892         5656 :       Move_ordered_evals moe(b);
     893         5656 :       mie->traverse_subexpressions(&moe);
     894              : 
     895              :       // Copy the key into a temporary so that we can take its address
     896              :       // without pushing the value onto the heap.
     897              : 
     898              :       // var key_temp KEY_TYPE = MAP_INDEX
     899         5656 :       Temporary_statement* key_temp = Statement::make_temporary(mt->key_type(),
     900              :                                                                 mie->index(),
     901              :                                                                 loc);
     902         5656 :       b->add_statement(key_temp);
     903              : 
     904              :       // Copy the value into a temporary to ensure that it is
     905              :       // evaluated before we add the key to the map.  This may matter
     906              :       // if the value is itself a reference to the map.
     907              : 
     908              :       // var val_temp VAL_TYPE = RHS
     909         5656 :       Temporary_statement* val_temp = Statement::make_temporary(mt->val_type(),
     910              :                                                                 this->rhs_,
     911              :                                                                 loc);
     912         5656 :       b->add_statement(val_temp);
     913              : 
     914              :       // *mapassign(TYPE, MAP, &key_temp) = RHS
     915         5656 :       Expression* a1 = Expression::make_type_descriptor(mt, loc);
     916         5656 :       Expression* a2 = mie->map();
     917         5656 :       Temporary_reference_expression* ref =
     918         5656 :         Expression::make_temporary_reference(key_temp, loc);
     919         5656 :       Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
     920         5656 :       Runtime::Function code;
     921         5656 :       Map_type::Map_alg alg = mt->algorithm(gogo);
     922         5656 :       switch (alg)
     923              :         {
     924          323 :           case Map_type::MAP_ALG_FAST32:
     925          323 :             {
     926          323 :               code = Runtime::MAPASSIGN_FAST32;
     927          323 :               Type* uint32_type = Type::lookup_integer_type("uint32");
     928          323 :               Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
     929          323 :               a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
     930              :                                                 loc);
     931          323 :               a3 = Expression::make_dereference(a3,
     932              :                                                 Expression::NIL_CHECK_NOT_NEEDED,
     933              :                                                 loc);
     934          323 :               break;
     935              :             }
     936          776 :           case Map_type::MAP_ALG_FAST64:
     937          776 :             {
     938          776 :               code = Runtime::MAPASSIGN_FAST64;
     939          776 :               Type* uint64_type = Type::lookup_integer_type("uint64");
     940          776 :               Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
     941          776 :               a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
     942              :                                                 loc);
     943          776 :               a3 = Expression::make_dereference(a3,
     944              :                                                 Expression::NIL_CHECK_NOT_NEEDED,
     945              :                                                 loc);
     946          776 :               break;
     947              :             }
     948          593 :           case Map_type::MAP_ALG_FAST32PTR:
     949          593 :           case Map_type::MAP_ALG_FAST64PTR:
     950          593 :             {
     951          328 :               code = (alg == Map_type::MAP_ALG_FAST32PTR
     952          593 :                       ? Runtime::MAPASSIGN_FAST32PTR
     953              :                       : Runtime::MAPASSIGN_FAST64PTR);
     954          593 :               Type* ptr_type =
     955          593 :                 Type::make_pointer_type(Type::make_void_type());
     956          593 :               Type* ptr_ptr_type = Type::make_pointer_type(ptr_type);
     957          593 :               a3 = Expression::make_unsafe_cast(ptr_ptr_type, a3,
     958              :                                                 loc);
     959          593 :               a3 = Expression::make_dereference(a3,
     960              :                                                 Expression::NIL_CHECK_NOT_NEEDED,
     961              :                                                 loc);
     962          593 :               break;
     963              :             }
     964              :           case Map_type::MAP_ALG_FASTSTR:
     965              :             code = Runtime::MAPASSIGN_FASTSTR;
     966              :             a3 = ref;
     967              :             break;
     968         1309 :           default:
     969         1309 :             code = Runtime::MAPASSIGN;
     970         1309 :             break;
     971              :         }
     972         5656 :       Expression* call = Runtime::make_call(gogo, code, loc, 3,
     973              :                                             a1, a2, a3);
     974         5656 :       Type* ptrval_type = Type::make_pointer_type(mt->val_type());
     975         5656 :       call = Expression::make_cast(ptrval_type, call, loc);
     976         5656 :       Expression* indir =
     977         5656 :           Expression::make_dereference(call, Expression::NIL_CHECK_NOT_NEEDED,
     978              :                                        loc);
     979         5656 :       ref = Expression::make_temporary_reference(val_temp, loc);
     980         5656 :       Statement* s = Statement::make_assignment(indir, ref, loc);
     981         5656 :       s->determine_types(gogo);
     982         5656 :       b->add_statement(s);
     983              : 
     984         5656 :       return Statement::make_block_statement(b, loc);
     985         5656 :     }
     986              : 
     987              :   // An assignment of the form s = s[:n] does not require a write
     988              :   // barrier, because the pointer value will not change.
     989      1382568 :   Array_index_expression* aie = this->rhs_->array_index_expression();
     990        70177 :   if (aie != NULL
     991        70177 :       && aie->end() != NULL
     992        14092 :       && Expression::is_same_variable(this->lhs_, aie->array()))
     993              :     {
     994         8161 :       Numeric_constant nc;
     995         8161 :       unsigned long ival;
     996         8161 :       if (aie->start()->numeric_constant_value(&nc)
     997         6158 :           && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
     998        14319 :           && ival == 0)
     999         4034 :         this->omit_write_barrier_ = true;
    1000         8161 :     }
    1001      1382568 :   String_index_expression* sie = this->rhs_->string_index_expression();
    1002         6799 :   if (sie != NULL
    1003         6799 :       && sie->end() != NULL
    1004         5973 :       && Expression::is_same_variable(this->lhs_, sie->string()))
    1005              :     {
    1006         3978 :       Numeric_constant nc;
    1007         3978 :       unsigned long ival;
    1008         3978 :       if (sie->start()->numeric_constant_value(&nc)
    1009         2917 :           && nc.to_unsigned_long(&ival) == Numeric_constant::NC_UL_VALID
    1010         6895 :           && ival == 0)
    1011          829 :         this->omit_write_barrier_ = true;
    1012         3978 :     }
    1013              : 
    1014      1382568 :   return this;
    1015              : }
    1016              : 
    1017              : // Set types for the assignment.
    1018              : 
    1019              : void
    1020      1468632 : Assignment_statement::do_determine_types(Gogo* gogo)
    1021              : {
    1022      1468632 :   this->lhs_->determine_type_no_context(gogo);
    1023      1468632 :   Type* rhs_context_type = this->lhs_->type();
    1024      1468632 :   if (rhs_context_type->is_sink_type())
    1025         7388 :     rhs_context_type = NULL;
    1026      1468632 :   Type_context context(rhs_context_type, false);
    1027      1468632 :   this->rhs_->determine_type(gogo, &context);
    1028      1468632 : }
    1029              : 
    1030              : // Check types for an assignment from RHS to LHS.  Returns true if the
    1031              : // assignment is OK.
    1032              : 
    1033              : bool
    1034       318331 : Assignment_statement::check_assignment_types(Expression* lhs,
    1035              :                                              Type* rhs_type,
    1036              :                                              Location loc)
    1037              : {
    1038              :   // The left hand side must be either addressable, a map index
    1039              :   // expression, or the blank identifier.
    1040       318331 :   if (!lhs->is_addressable()
    1041        33028 :       && !Index_expression::is_map_index(lhs)
    1042       345940 :       && !lhs->is_sink_expression())
    1043              :     {
    1044            8 :       if (!lhs->type()->is_error())
    1045            8 :         go_error_at(lhs->location(), "invalid left hand side of assignment");
    1046            8 :       return false;
    1047              :     }
    1048              : 
    1049       318323 :   Type* lhs_type = lhs->type();
    1050              : 
    1051              :   // Check for invalid assignment of nil to the blank identifier.
    1052       318323 :   if (lhs_type->is_sink_type() && rhs_type->is_nil_type())
    1053              :     {
    1054            3 :       go_error_at(loc, "use of untyped nil");
    1055            3 :       return false;
    1056              :     }
    1057              : 
    1058       318320 :   std::string reason;
    1059       318320 :   if (!Type::are_assignable(lhs_type, rhs_type, &reason))
    1060              :     {
    1061           96 :       if (reason.empty())
    1062            0 :         go_error_at(loc, "incompatible types in assignment");
    1063              :       else
    1064           96 :         go_error_at(loc, "incompatible types in assignment (%s)",
    1065              :                     reason.c_str());
    1066           96 :       return false;
    1067              :     }
    1068              : 
    1069       318224 :   if (lhs_type->is_error_type() || rhs_type->is_error_type())
    1070           61 :     return false;
    1071              : 
    1072              :   return true;
    1073       318320 : }
    1074              : 
    1075              : // Check types for an assignment.
    1076              : 
    1077              : void
    1078       193257 : Assignment_statement::do_check_types(Gogo*)
    1079              : {
    1080       193257 :   if (!Assignment_statement::check_assignment_types(this->lhs_,
    1081       193257 :                                                     this->rhs_->type(),
    1082              :                                                     this->location()))
    1083          159 :     this->set_is_error();
    1084       193257 : }
    1085              : 
    1086              : void
    1087        20287 : Assignment_statement::do_export_statement(Export_function_body* efb)
    1088              : {
    1089        20287 :   this->lhs_->export_expression(efb);
    1090        20287 :   efb->write_c_string(" = ");
    1091        20287 :   this->rhs_->export_expression(efb);
    1092        20287 : }
    1093              : 
    1094              : // Flatten an assignment statement.  We may need a temporary for
    1095              : // interface conversion.
    1096              : 
    1097              : Statement*
    1098      1142087 : Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
    1099              :                                  Statement_inserter* inserter)
    1100              : {
    1101      1142087 :   if (this->lhs_->is_error_expression()
    1102      1142086 :       || this->lhs_->type()->is_error_type()
    1103      1142085 :       || this->rhs_->is_error_expression()
    1104      2283910 :       || this->rhs_->type()->is_error_type())
    1105              :     {
    1106          269 :       go_assert(saw_errors());
    1107          269 :       return Statement::make_error_statement(this->location());
    1108              :     }
    1109              : 
    1110      1141818 :   if (!this->lhs_->is_sink_expression()
    1111      1135239 :       && !Type::are_identical(this->lhs_->type(), this->rhs_->type(),
    1112              :                               Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
    1113              :                               NULL)
    1114        16722 :       && this->rhs_->type()->interface_type() != NULL
    1115      1141818 :       && !this->rhs_->is_multi_eval_safe())
    1116              :     {
    1117            0 :       Temporary_statement* temp =
    1118            0 :         Statement::make_temporary(NULL, this->rhs_, this->location());
    1119            0 :       inserter->insert(temp);
    1120            0 :       this->rhs_ = Expression::make_temporary_reference(temp,
    1121              :                                                         this->location());
    1122              :     }
    1123      1141818 :   return this;
    1124              : }
    1125              : 
    1126              : // Add explicit type conversions.
    1127              : 
    1128              : void
    1129       727201 : Assignment_statement::do_add_conversions()
    1130              : {
    1131       727201 :   Type* lt = this->lhs_->type();
    1132       727201 :   Type* rt = this->rhs_->type();
    1133       727201 :   if (!Type::are_identical(lt, rt, 0, NULL)
    1134       727201 :       && lt->interface_type() != NULL)
    1135        20556 :     this->rhs_ = Expression::make_cast(lt, this->rhs_, this->location());
    1136       727201 : }
    1137              : 
    1138              : // Convert an assignment statement to the backend representation.
    1139              : 
    1140              : Bstatement*
    1141      1225071 : Assignment_statement::do_get_backend(Translate_context* context)
    1142              : {
    1143      1225071 :   if (this->lhs_->is_sink_expression())
    1144              :     {
    1145         4494 :       Bexpression* rhs = this->rhs_->get_backend(context);
    1146         4494 :       Bfunction* bfunction = context->function()->func_value()->get_decl();
    1147         4494 :       return context->backend()->expression_statement(bfunction, rhs);
    1148              :     }
    1149              : 
    1150      1220577 :   Bexpression* lhs = this->lhs_->get_backend(context);
    1151      1220577 :   Expression* conv =
    1152      1220577 :       Expression::convert_for_assignment(context->gogo(), this->lhs_->type(),
    1153              :                                          this->rhs_, this->location());
    1154      1220577 :   Bexpression* rhs = conv->get_backend(context);
    1155      1220577 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    1156      1220577 :   return context->backend()->assignment_statement(bfunction, lhs, rhs,
    1157      1220577 :                                                   this->location());
    1158              : }
    1159              : 
    1160              : // Dump the AST representation for an assignment statement.
    1161              : 
    1162              : void
    1163            0 : Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    1164              :     const
    1165              : {
    1166            0 :   ast_dump_context->print_indent();
    1167            0 :   ast_dump_context->dump_expression(this->lhs_);
    1168            0 :   ast_dump_context->ostream() << " = " ;
    1169            0 :   ast_dump_context->dump_expression(this->rhs_);
    1170            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    1171            0 : }
    1172              : 
    1173              : // Make an assignment statement.
    1174              : 
    1175              : Assignment_statement*
    1176      1341151 : Statement::make_assignment(Expression* lhs, Expression* rhs,
    1177              :                            Location location)
    1178              : {
    1179      1341151 :   Temporary_reference_expression* tre = lhs->temporary_reference_expression();
    1180       214339 :   if (tre != NULL)
    1181       214339 :     tre->statement()->set_assigned();
    1182      1341151 :   return new Assignment_statement(lhs, rhs, location);
    1183              : }
    1184              : 
    1185              : // An assignment operation statement.
    1186              : 
    1187              : class Assignment_operation_statement : public Statement
    1188              : {
    1189              :  public:
    1190        84155 :   Assignment_operation_statement(Operator op, Expression* lhs, Expression* rhs,
    1191              :                                  Location location)
    1192        84155 :     : Statement(STATEMENT_ASSIGNMENT_OPERATION, location),
    1193       168310 :       op_(op), lhs_(lhs), rhs_(rhs)
    1194              :   { }
    1195              : 
    1196              :  protected:
    1197              :   int
    1198              :   do_traverse(Traverse*);
    1199              : 
    1200              :   void
    1201              :   do_determine_types(Gogo*);
    1202              : 
    1203              :   void
    1204              :   do_check_types(Gogo*);
    1205              : 
    1206              :   Statement*
    1207              :   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
    1208              : 
    1209              :   Bstatement*
    1210            0 :   do_get_backend(Translate_context*)
    1211            0 :   { go_unreachable(); }
    1212              : 
    1213              :   void
    1214              :   do_dump_statement(Ast_dump_context*) const;
    1215              : 
    1216              :  private:
    1217              :   Operator
    1218              :   get_binop();
    1219              : 
    1220              :   // The operator (OPERATOR_PLUSEQ, etc.).
    1221              :   Operator op_;
    1222              :   // Left hand side.
    1223              :   Expression* lhs_;
    1224              :   // Right hand side.
    1225              :   Expression* rhs_;
    1226              : };
    1227              : 
    1228              : // Traversal.
    1229              : 
    1230              : int
    1231       185363 : Assignment_operation_statement::do_traverse(Traverse* traverse)
    1232              : {
    1233       185363 :   if (this->traverse_expression(traverse, &this->lhs_) == TRAVERSE_EXIT)
    1234              :     return TRAVERSE_EXIT;
    1235       185363 :   return this->traverse_expression(traverse, &this->rhs_);
    1236              : }
    1237              : 
    1238              : void
    1239        25309 : Assignment_operation_statement::do_determine_types(Gogo* gogo)
    1240              : {
    1241        25309 :   this->lhs_->determine_type_no_context(gogo);
    1242        25309 :   Type* rhs_context_type = this->lhs_->type();
    1243        25309 :   if (rhs_context_type->is_sink_type())
    1244            0 :     rhs_context_type = NULL;
    1245        25309 :   Type_context context(rhs_context_type, false);
    1246        25309 :   this->rhs_->determine_type(gogo, &context);
    1247        25309 : }
    1248              : 
    1249              : // Get the binary operator from the assignment operator.
    1250              : 
    1251              : Operator
    1252       107708 : Assignment_operation_statement::get_binop()
    1253              : {
    1254       107708 :   switch (this->op_)
    1255              :     {
    1256              :     case OPERATOR_PLUSEQ:
    1257              :       return OPERATOR_PLUS;
    1258              :     case OPERATOR_MINUSEQ:
    1259              :       return OPERATOR_MINUS;
    1260              :     case OPERATOR_OREQ:
    1261              :       return OPERATOR_OR;
    1262              :     case OPERATOR_XOREQ:
    1263              :       return OPERATOR_XOR;
    1264              :     case OPERATOR_MULTEQ:
    1265              :       return OPERATOR_MULT;
    1266              :     case OPERATOR_DIVEQ:
    1267              :       return OPERATOR_DIV;
    1268              :     case OPERATOR_MODEQ:
    1269              :       return OPERATOR_MOD;
    1270              :     case OPERATOR_LSHIFTEQ:
    1271              :       return OPERATOR_LSHIFT;
    1272              :     case OPERATOR_RSHIFTEQ:
    1273              :       return OPERATOR_RSHIFT;
    1274              :     case OPERATOR_ANDEQ:
    1275              :       return OPERATOR_AND;
    1276              :     case OPERATOR_BITCLEAREQ:
    1277              :       return OPERATOR_BITCLEAR;
    1278            0 :     default:
    1279            0 :       go_unreachable();
    1280              :     }
    1281              : }
    1282              : 
    1283              : void
    1284        25309 : Assignment_operation_statement::do_check_types(Gogo*)
    1285              : {
    1286        25309 :   if (this->lhs_->is_sink_expression())
    1287              :     {
    1288            0 :       this->report_error(_("cannot use %<_%> as value"));
    1289            0 :       return;
    1290              :     }
    1291              : 
    1292              : 
    1293        25309 :   Type* lhs_type = this->lhs_->type();
    1294        25309 :   Type* rhs_type = this->rhs_->type();
    1295              : 
    1296        25309 :   if (!this->lhs_->is_addressable()
    1297        25309 :       && !Index_expression::is_map_index(this->lhs_))
    1298              :     {
    1299            0 :       if (!lhs_type->is_error())
    1300            0 :         this->report_error(_("invalid left hand side of assignment"));
    1301            0 :       this->set_is_error();
    1302            0 :       return;
    1303              :     }
    1304              : 
    1305        25309 :   if (this->op_ != OPERATOR_LSHIFTEQ && this->op_ != OPERATOR_RSHIFTEQ)
    1306              :     {
    1307        23581 :       if (!Type::are_compatible_for_binop(lhs_type, rhs_type))
    1308              :         {
    1309            0 :           this->report_error(_("incompatible type in binary expression"));
    1310            0 :           return;
    1311              :         }
    1312        23581 :       if (!Binary_expression::check_operator_type(this->get_binop(), lhs_type,
    1313              :                                                   rhs_type, this->location()))
    1314              :         {
    1315            1 :           this->set_is_error();
    1316            1 :           return;
    1317              :         }
    1318        23580 :       if (this->op_ == OPERATOR_DIVEQ || this->op_ == OPERATOR_MODEQ)
    1319              :         {
    1320          461 :           Numeric_constant rconst;
    1321          461 :           unsigned long rval;
    1322          461 :           if (lhs_type->integer_type() != NULL
    1323          370 :               && this->rhs_->numeric_constant_value(&rconst)
    1324          332 :               && rconst.to_unsigned_long(&rval) == Numeric_constant::NC_UL_VALID
    1325          332 :               && rval == 0)
    1326              :             {
    1327            0 :               this->report_error(_("integer division by zero"));
    1328            0 :               return;
    1329              :             }
    1330          461 :         }
    1331              :     }
    1332              :   else
    1333              :     {
    1334         1728 :       if (lhs_type->integer_type() == NULL)
    1335              :         {
    1336            0 :           this->report_error(_("shift of non-integer operand"));
    1337            0 :           return;
    1338              :         }
    1339              : 
    1340         1728 :       if (rhs_type->is_string_type()
    1341         1728 :           || (!rhs_type->is_abstract()
    1342         1728 :               && rhs_type->integer_type() == NULL))
    1343              :         {
    1344            0 :           this->report_error(_("shift count not integer"));
    1345            0 :           return;
    1346              :         }
    1347              : 
    1348         1728 :       Numeric_constant nc;
    1349         1728 :       if (this->rhs_->numeric_constant_value(&nc))
    1350              :         {
    1351         1462 :           mpz_t val;
    1352         1462 :           if (!nc.to_int(&val))
    1353              :             {
    1354            0 :               this->report_error(_("shift count not integer"));
    1355            0 :               return;
    1356              :             }
    1357         1462 :           if (mpz_sgn(val) < 0)
    1358            0 :             this->report_error(_("negative shift count"));
    1359         1462 :           mpz_clear(val);
    1360              :         }
    1361         1728 :     }
    1362              : }
    1363              : 
    1364              : // Lower an assignment operation statement to a regular assignment
    1365              : // statement.
    1366              : 
    1367              : Statement*
    1368        84127 : Assignment_operation_statement::do_lower(Gogo* gogo, Named_object*,
    1369              :                                          Block* enclosing, Statement_inserter*)
    1370              : {
    1371        84127 :   Location loc = this->location();
    1372              : 
    1373              :   // We have to evaluate the left hand side expression only once.  We
    1374              :   // do this by moving out any expression with side effects.
    1375        84127 :   Block* b = new Block(enclosing, loc);
    1376        84127 :   Move_ordered_evals moe(b);
    1377        84127 :   this->lhs_->traverse_subexpressions(&moe);
    1378              : 
    1379              :   // We can still be left with subexpressions that have to be loaded
    1380              :   // even if they don't have side effects themselves, in case the RHS
    1381              :   // changes variables named on the LHS.
    1382        84127 :   int i;
    1383        84127 :   if (this->lhs_->must_eval_subexpressions_in_order(&i))
    1384              :     {
    1385         2449 :       Move_subexpressions ms(i, b);
    1386         2449 :       this->lhs_->traverse_subexpressions(&ms);
    1387         2449 :     }
    1388              : 
    1389        84127 :   Expression* lval = this->lhs_->copy();
    1390              : 
    1391        84127 :   Expression* binop = Expression::make_binary(this->get_binop(), lval,
    1392              :                                               this->rhs_, loc);
    1393        84127 :   Statement* s = Statement::make_assignment(this->lhs_, binop, loc);
    1394        84127 :   s->determine_types(gogo);
    1395        84127 :   if (b->statements()->empty())
    1396              :     {
    1397        75389 :       delete b;
    1398        75389 :       return s;
    1399              :     }
    1400              :   else
    1401              :     {
    1402         8738 :       b->add_statement(s);
    1403         8738 :       return Statement::make_block_statement(b, loc);
    1404              :     }
    1405        84127 : }
    1406              : 
    1407              : // Dump the AST representation for an assignment operation statement
    1408              : 
    1409              : void
    1410            0 : Assignment_operation_statement::do_dump_statement(
    1411              :     Ast_dump_context* ast_dump_context) const
    1412              : {
    1413            0 :   ast_dump_context->print_indent();
    1414            0 :   ast_dump_context->dump_expression(this->lhs_);
    1415            0 :   ast_dump_context->dump_operator(this->op_);
    1416            0 :   ast_dump_context->dump_expression(this->rhs_);
    1417            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    1418            0 : }
    1419              : 
    1420              : // Make an assignment operation statement.
    1421              : 
    1422              : Statement*
    1423        84155 : Statement::make_assignment_operation(Operator op, Expression* lhs,
    1424              :                                      Expression* rhs, Location location)
    1425              : {
    1426        84155 :   return new Assignment_operation_statement(op, lhs, rhs, location);
    1427              : }
    1428              : 
    1429              : // A tuple assignment statement.  This differs from an assignment
    1430              : // statement in that the right-hand-side expressions are evaluated in
    1431              : // parallel.
    1432              : 
    1433              : class Tuple_assignment_statement : public Statement
    1434              : {
    1435              :  public:
    1436       103919 :   Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
    1437              :                              Location location)
    1438       103919 :     : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
    1439       207838 :       lhs_(lhs), rhs_(rhs)
    1440              :   { }
    1441              : 
    1442              :  protected:
    1443              :   int
    1444              :   do_traverse(Traverse* traverse);
    1445              : 
    1446              :   void
    1447              :   do_determine_types(Gogo*);
    1448              : 
    1449              :   void
    1450              :   do_check_types(Gogo*);
    1451              : 
    1452              :   Statement*
    1453              :   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
    1454              : 
    1455              :   Bstatement*
    1456            0 :   do_get_backend(Translate_context*)
    1457            0 :   { go_unreachable(); }
    1458              : 
    1459              :   void
    1460              :   do_dump_statement(Ast_dump_context*) const;
    1461              : 
    1462              :  private:
    1463              :   // Left hand side--a list of lvalues.
    1464              :   Expression_list* lhs_;
    1465              :   // Right hand side--a list of rvalues.
    1466              :   Expression_list* rhs_;
    1467              : };
    1468              : 
    1469              : // Traversal.
    1470              : 
    1471              : int
    1472       214525 : Tuple_assignment_statement::do_traverse(Traverse* traverse)
    1473              : {
    1474       214525 :   if (this->traverse_expression_list(traverse, this->lhs_) == TRAVERSE_EXIT)
    1475              :     return TRAVERSE_EXIT;
    1476       214525 :   return this->traverse_expression_list(traverse, this->rhs_);
    1477              : }
    1478              : 
    1479              : void
    1480       126171 : Tuple_assignment_statement::do_determine_types(Gogo* gogo)
    1481              : {
    1482       126171 :   Expression_list::iterator pr = this->rhs_->begin();
    1483       126171 :   for (Expression_list::iterator pl = this->lhs_->begin();
    1484       391441 :        pl != this->lhs_->end();
    1485       265270 :        ++pl, ++pr)
    1486              :     {
    1487       265270 :       go_assert(pr != this->rhs_->end());
    1488       265270 :       (*pl)->determine_type_no_context(gogo);
    1489       265270 :       Type* rhs_context_type = (*pl)->type();
    1490       265270 :       if (rhs_context_type->is_sink_type())
    1491        36878 :         rhs_context_type = NULL;
    1492       265270 :       Type_context context(rhs_context_type, false);
    1493       265270 :       (*pr)->determine_type(gogo, &context);
    1494              :     }
    1495       126171 :   go_assert(pr == this->rhs_->end());
    1496       126171 : }
    1497              : 
    1498              : void
    1499        27653 : Tuple_assignment_statement::do_check_types(Gogo*)
    1500              : {
    1501        27653 :   Expression_list::iterator pr = this->rhs_->begin();
    1502        27653 :   for (Expression_list::iterator pl = this->lhs_->begin();
    1503        86520 :        pl != this->lhs_->end();
    1504        58867 :        ++pl, ++pr)
    1505              :     {
    1506        58867 :       go_assert(pr != this->rhs_->end());
    1507        58867 :       if (!Assignment_statement::check_assignment_types(*pl, (*pr)->type(),
    1508              :                                                         this->location()))
    1509            8 :         this->set_is_error();
    1510              :     }
    1511        27653 :   go_assert(pr == this->rhs_->end());
    1512        27653 : }
    1513              : 
    1514              : // Lower a tuple assignment.  We use temporary variables to split it
    1515              : // up into a set of single assignments.
    1516              : 
    1517              : Statement*
    1518       103913 : Tuple_assignment_statement::do_lower(Gogo* gogo, Named_object*,
    1519              :                                      Block* enclosing, Statement_inserter*)
    1520              : {
    1521       103913 :   Location loc = this->location();
    1522              : 
    1523       103913 :   if (this->classification() == STATEMENT_ERROR)
    1524            0 :     return Statement::make_error_statement(loc);
    1525              : 
    1526       103913 :   Block* b = new Block(enclosing, loc);
    1527              : 
    1528              :   // First move out any subexpressions on the left hand side.  The
    1529              :   // right hand side will be evaluated in the required order anyhow.
    1530       103913 :   Move_ordered_evals moe(b);
    1531       324664 :   for (Expression_list::iterator plhs = this->lhs_->begin();
    1532       324664 :        plhs != this->lhs_->end();
    1533       220751 :        ++plhs)
    1534       220751 :     Expression::traverse(&*plhs, &moe);
    1535              : 
    1536       103913 :   std::vector<Temporary_statement*> temps;
    1537       103913 :   temps.reserve(this->lhs_->size());
    1538              : 
    1539       103913 :   Expression_list::const_iterator prhs = this->rhs_->begin();
    1540       103913 :   for (Expression_list::const_iterator plhs = this->lhs_->begin();
    1541       324664 :        plhs != this->lhs_->end();
    1542       220751 :        ++plhs, ++prhs)
    1543              :     {
    1544       220751 :       go_assert(prhs != this->rhs_->end());
    1545              : 
    1546       220751 :       if ((*plhs)->is_error_expression()
    1547       220751 :           || (*plhs)->type()->is_error()
    1548       220750 :           || (*prhs)->is_error_expression()
    1549       441495 :           || (*prhs)->type()->is_error())
    1550        20510 :         continue;
    1551              : 
    1552       220744 :       if ((*plhs)->is_sink_expression())
    1553              :         {
    1554        20503 :           if ((*prhs)->type()->is_nil_type())
    1555            0 :             this->report_error(_("use of untyped nil"));
    1556              :           else
    1557        20503 :             b->add_statement(Statement::make_statement(*prhs, true));
    1558        20503 :           continue;
    1559              :         }
    1560              : 
    1561       200241 :       Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
    1562       200241 :                                                             *prhs, loc);
    1563       200241 :       b->add_statement(temp);
    1564       200241 :       temps.push_back(temp);
    1565              : 
    1566              :     }
    1567       103913 :   go_assert(prhs == this->rhs_->end());
    1568              : 
    1569       103913 :   prhs = this->rhs_->begin();
    1570       103913 :   std::vector<Temporary_statement*>::const_iterator ptemp = temps.begin();
    1571       103913 :   for (Expression_list::const_iterator plhs = this->lhs_->begin();
    1572       324664 :        plhs != this->lhs_->end();
    1573       220751 :        ++plhs, ++prhs)
    1574              :     {
    1575       220751 :       if ((*plhs)->is_error_expression()
    1576       220751 :           || (*plhs)->type()->is_error()
    1577       220750 :           || (*prhs)->is_error_expression()
    1578       441495 :           || (*prhs)->type()->is_error())
    1579            7 :         continue;
    1580              : 
    1581       220744 :       if ((*plhs)->is_sink_expression())
    1582        20503 :         continue;
    1583              : 
    1584       200241 :       Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
    1585       200241 :       Statement* s = Statement::make_assignment(*plhs, ref, loc);
    1586       200241 :       s->determine_types(gogo);
    1587       200241 :       b->add_statement(s);
    1588       200241 :       ++ptemp;
    1589              :     }
    1590       103913 :   go_assert(ptemp == temps.end() || saw_errors());
    1591              : 
    1592       103913 :   return Statement::make_block_statement(b, loc);
    1593       103913 : }
    1594              : 
    1595              : // Dump the AST representation for a tuple assignment statement.
    1596              : 
    1597              : void
    1598            0 : Tuple_assignment_statement::do_dump_statement(
    1599              :     Ast_dump_context* ast_dump_context) const
    1600              : {
    1601            0 :   ast_dump_context->print_indent();
    1602            0 :   ast_dump_context->dump_expression_list(this->lhs_);
    1603            0 :   ast_dump_context->ostream() << " = ";
    1604            0 :   ast_dump_context->dump_expression_list(this->rhs_);
    1605            0 :   ast_dump_context->ostream()  << dsuffix(location()) << std::endl;
    1606            0 : }
    1607              : 
    1608              : // Make a tuple assignment statement.
    1609              : 
    1610              : Statement*
    1611       103919 : Statement::make_tuple_assignment(Expression_list* lhs, Expression_list* rhs,
    1612              :                                  Location location)
    1613              : {
    1614       103919 :   return new Tuple_assignment_statement(lhs, rhs, location);
    1615              : }
    1616              : 
    1617              : // A tuple assignment from a map index expression.
    1618              : //   v, ok = m[k]
    1619              : 
    1620              : class Tuple_map_assignment_statement : public Statement
    1621              : {
    1622              : public:
    1623         2365 :   Tuple_map_assignment_statement(Expression* val, Expression* present,
    1624              :                                  Expression* map_index,
    1625              :                                  Location location)
    1626         2365 :     : Statement(STATEMENT_TUPLE_MAP_ASSIGNMENT, location),
    1627         4730 :       val_(val), present_(present), map_index_(map_index)
    1628              :   { }
    1629              : 
    1630              :  protected:
    1631              :   int
    1632              :   do_traverse(Traverse* traverse);
    1633              : 
    1634              :   void
    1635              :   do_determine_types(Gogo*);
    1636              : 
    1637              :   void
    1638              :   do_check_types(Gogo*);
    1639              : 
    1640              :   Statement*
    1641              :   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
    1642              : 
    1643              :   Bstatement*
    1644            0 :   do_get_backend(Translate_context*)
    1645            0 :   { go_unreachable(); }
    1646              : 
    1647              :   void
    1648              :   do_dump_statement(Ast_dump_context*) const;
    1649              : 
    1650              :  private:
    1651              :   // Lvalue which receives the value from the map.
    1652              :   Expression* val_;
    1653              :   // Lvalue which receives whether the key value was present.
    1654              :   Expression* present_;
    1655              :   // The map index expression.
    1656              :   Expression* map_index_;
    1657              : };
    1658              : 
    1659              : // Traversal.
    1660              : 
    1661              : int
    1662        11825 : Tuple_map_assignment_statement::do_traverse(Traverse* traverse)
    1663              : {
    1664        11825 :   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
    1665        11825 :       || this->traverse_expression(traverse, &this->present_) == TRAVERSE_EXIT)
    1666            0 :     return TRAVERSE_EXIT;
    1667        11825 :   return this->traverse_expression(traverse, &this->map_index_);
    1668              : }
    1669              : 
    1670              : void
    1671         2365 : Tuple_map_assignment_statement::do_determine_types(Gogo* gogo)
    1672              : {
    1673         2365 :   this->val_->determine_type_no_context(gogo);
    1674         2365 :   this->present_->determine_type_no_context(gogo);
    1675         2365 :   this->map_index_->determine_type_no_context(gogo);
    1676         2365 : }
    1677              : 
    1678              : void
    1679         2365 : Tuple_map_assignment_statement::do_check_types(Gogo*)
    1680              : {
    1681         2365 :   Expression* map_expr = this->map_index_;
    1682         2365 :   Map_type* map_type;
    1683         2365 :   if (map_expr->map_index_expression() != NULL)
    1684            0 :     map_type = map_expr->map_index_expression()->get_map_type();
    1685         2365 :   else if (map_expr->index_expression() != NULL)
    1686         2365 :     map_type = map_expr->index_expression()->left()->type()->map_type();
    1687              :   else
    1688              :     {
    1689            0 :       this->report_error(_("expected map index on right hand side"));
    1690            0 :       return;
    1691              :     }
    1692         2365 :   if (map_type == NULL || map_type->is_error())
    1693              :     {
    1694            0 :       go_assert(saw_errors());
    1695            0 :       this->set_is_error();
    1696            0 :       return;
    1697              :     }
    1698              : 
    1699         2365 :   if (!Assignment_statement::check_assignment_types(this->val_,
    1700              :                                                     map_type->val_type(),
    1701              :                                                     this->location()))
    1702            0 :     this->set_is_error();
    1703         2365 :   if (!Assignment_statement::check_assignment_types(this->present_,
    1704              :                                                     Type::make_boolean_type(),
    1705              :                                                     this->location()))
    1706            0 :     this->set_is_error();
    1707              : }
    1708              : 
    1709              : // Lower a tuple map assignment.
    1710              : 
    1711              : Statement*
    1712         2365 : Tuple_map_assignment_statement::do_lower(Gogo* gogo, Named_object*,
    1713              :                                          Block* enclosing, Statement_inserter*)
    1714              : {
    1715         2365 :   Location loc = this->location();
    1716              : 
    1717         2365 :   if (this->classification() == STATEMENT_ERROR)
    1718            0 :     return Statement::make_error_statement(loc);
    1719              : 
    1720         2365 :   Map_index_expression* map_index = this->map_index_->map_index_expression();
    1721            0 :   go_assert(map_index != NULL);
    1722         2365 :   Map_type* map_type = map_index->get_map_type();
    1723         2365 :   go_assert(map_type != NULL);
    1724              : 
    1725              :   // Avoid copy for string([]byte) conversions used in map keys.
    1726              :   // mapaccess doesn't keep the reference, so this is safe.
    1727         2365 :   Type_conversion_expression* ce = map_index->index()->conversion_expression();
    1728           31 :   if (ce != NULL && ce->type()->is_string_type()
    1729           26 :       && ce->expr()->type()->is_slice_type())
    1730           26 :     ce->set_no_copy(true);
    1731              : 
    1732         2365 :   Block* b = new Block(enclosing, loc);
    1733              : 
    1734              :   // Move out any subexpressions to make sure that functions are
    1735              :   // called in the required order.
    1736         2365 :   Move_ordered_evals moe(b);
    1737         2365 :   this->val_->traverse_subexpressions(&moe);
    1738         2365 :   this->present_->traverse_subexpressions(&moe);
    1739              : 
    1740              :   // Copy the key value into a temporary so that we can take its
    1741              :   // address without pushing the value onto the heap.
    1742              : 
    1743              :   // var key_temp KEY_TYPE = MAP_INDEX
    1744         2365 :   Temporary_statement* key_temp =
    1745         2365 :     Statement::make_temporary(map_type->key_type(), map_index->index(), loc);
    1746         2365 :   b->add_statement(key_temp);
    1747              : 
    1748              :   // var val_ptr_temp *VAL_TYPE
    1749         2365 :   Type* val_ptr_type = Type::make_pointer_type(map_type->val_type());
    1750         2365 :   Temporary_statement* val_ptr_temp = Statement::make_temporary(val_ptr_type,
    1751              :                                                                 NULL, loc);
    1752         2365 :   b->add_statement(val_ptr_temp);
    1753              : 
    1754              :   // var present_temp bool
    1755         2365 :   Temporary_statement* present_temp =
    1756         4730 :     Statement::make_temporary((this->present_->type()->is_boolean_type()
    1757         2337 :                                ? this->present_->type()
    1758           28 :                                : Type::lookup_bool_type()),
    1759              :                               NULL, loc);
    1760         2365 :   b->add_statement(present_temp);
    1761              : 
    1762              :   // val_ptr_temp, present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp)
    1763         2365 :   Expression* a1 = Expression::make_type_descriptor(map_type, loc);
    1764         2365 :   Expression* a2 = map_index->map();
    1765         2365 :   Temporary_reference_expression* ref =
    1766         2365 :     Expression::make_temporary_reference(key_temp, loc);
    1767         2365 :   Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc);
    1768         2365 :   Expression* a4 = map_type->fat_zero_value(gogo);
    1769         2365 :   Call_expression* call;
    1770         2365 :   if (a4 == NULL)
    1771              :     {
    1772         2362 :       Runtime::Function code;
    1773         2362 :       Map_type::Map_alg alg = map_type->algorithm(gogo);
    1774         2362 :       switch (alg)
    1775              :         {
    1776          261 :           case Map_type::MAP_ALG_FAST32:
    1777          261 :           case Map_type::MAP_ALG_FAST32PTR:
    1778          261 :             {
    1779          261 :               code = Runtime::MAPACCESS2_FAST32;
    1780          261 :               Type* uint32_type = Type::lookup_integer_type("uint32");
    1781          261 :               Type* uint32_ptr_type = Type::make_pointer_type(uint32_type);
    1782          261 :               a3 = Expression::make_unsafe_cast(uint32_ptr_type, a3,
    1783              :                                                 loc);
    1784          261 :               a3 = Expression::make_dereference(a3,
    1785              :                                                 Expression::NIL_CHECK_NOT_NEEDED,
    1786              :                                                 loc);
    1787          261 :               break;
    1788              :             }
    1789          299 :           case Map_type::MAP_ALG_FAST64:
    1790          299 :           case Map_type::MAP_ALG_FAST64PTR:
    1791          299 :             {
    1792          299 :               code = Runtime::MAPACCESS2_FAST64;
    1793          299 :               Type* uint64_type = Type::lookup_integer_type("uint64");
    1794          299 :               Type* uint64_ptr_type = Type::make_pointer_type(uint64_type);
    1795          299 :               a3 = Expression::make_unsafe_cast(uint64_ptr_type, a3,
    1796              :                                                 loc);
    1797          299 :               a3 = Expression::make_dereference(a3,
    1798              :                                                 Expression::NIL_CHECK_NOT_NEEDED,
    1799              :                                                 loc);
    1800          299 :               break;
    1801              :             }
    1802              :           case Map_type::MAP_ALG_FASTSTR:
    1803              :             code = Runtime::MAPACCESS2_FASTSTR;
    1804              :             a3 = ref;
    1805              :             break;
    1806          523 :           default:
    1807          523 :             code = Runtime::MAPACCESS2;
    1808          523 :             break;
    1809              :         }
    1810         2362 :       call = Runtime::make_call(gogo, code, loc, 3, a1, a2, a3);
    1811              :     }
    1812              :   else
    1813            3 :     call = Runtime::make_call(gogo, Runtime::MAPACCESS2_FAT, loc, 4,
    1814              :                               a1, a2, a3, a4);
    1815         2365 :   ref = Expression::make_temporary_reference(val_ptr_temp, loc);
    1816         2365 :   ref->set_is_lvalue();
    1817         2365 :   Expression* res = Expression::make_call_result(call, 0);
    1818         2365 :   res = Expression::make_unsafe_cast(val_ptr_type, res, loc);
    1819         2365 :   Statement* s = Statement::make_assignment(ref, res, loc);
    1820         2365 :   s->determine_types(gogo);
    1821         2365 :   b->add_statement(s);
    1822         2365 :   ref = Expression::make_temporary_reference(present_temp, loc);
    1823         2365 :   ref->set_is_lvalue();
    1824         2365 :   res = Expression::make_call_result(call, 1);
    1825         2365 :   s = Statement::make_assignment(ref, res, loc);
    1826         2365 :   s->determine_types(gogo);
    1827         2365 :   b->add_statement(s);
    1828              : 
    1829              :   // val = *val__ptr_temp
    1830         2365 :   ref = Expression::make_temporary_reference(val_ptr_temp, loc);
    1831         2365 :   Expression* ind =
    1832         2365 :       Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED, loc);
    1833         2365 :   s = Statement::make_assignment(this->val_, ind, loc);
    1834         2365 :   s->determine_types(gogo);
    1835         2365 :   b->add_statement(s);
    1836              : 
    1837              :   // present = present_temp
    1838         2365 :   ref = Expression::make_temporary_reference(present_temp, loc);
    1839         2365 :   s = Statement::make_assignment(this->present_, ref, loc);
    1840         2365 :   s->determine_types(gogo);
    1841         2365 :   b->add_statement(s);
    1842              : 
    1843         2365 :   return Statement::make_block_statement(b, loc);
    1844         2365 : }
    1845              : 
    1846              : // Dump the AST representation for a tuple map assignment statement.
    1847              : 
    1848              : void
    1849            0 : Tuple_map_assignment_statement::do_dump_statement(
    1850              :     Ast_dump_context* ast_dump_context) const
    1851              : {
    1852            0 :   ast_dump_context->print_indent();
    1853            0 :   ast_dump_context->dump_expression(this->val_);
    1854            0 :   ast_dump_context->ostream() << ", ";
    1855            0 :   ast_dump_context->dump_expression(this->present_);
    1856            0 :   ast_dump_context->ostream() << " = ";
    1857            0 :   ast_dump_context->dump_expression(this->map_index_);
    1858            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    1859            0 : }
    1860              : 
    1861              : // Make a map assignment statement which returns a pair of values.
    1862              : 
    1863              : Statement*
    1864         2365 : Statement::make_tuple_map_assignment(Expression* val, Expression* present,
    1865              :                                      Expression* map_index,
    1866              :                                      Location location)
    1867              : {
    1868         2365 :   return new Tuple_map_assignment_statement(val, present, map_index, location);
    1869              : }
    1870              : 
    1871              : // A tuple assignment from a receive statement.
    1872              : 
    1873              : class Tuple_receive_assignment_statement : public Statement
    1874              : {
    1875              :  public:
    1876          186 :   Tuple_receive_assignment_statement(Expression* val, Expression* closed,
    1877              :                                      Expression* channel, Location location)
    1878          186 :     : Statement(STATEMENT_TUPLE_RECEIVE_ASSIGNMENT, location),
    1879          372 :       val_(val), closed_(closed), channel_(channel)
    1880              :   { }
    1881              : 
    1882              :  protected:
    1883              :   int
    1884              :   do_traverse(Traverse* traverse);
    1885              : 
    1886              :   void
    1887              :   do_determine_types(Gogo*);
    1888              : 
    1889              :   void
    1890              :   do_check_types(Gogo*);
    1891              : 
    1892              :   Statement*
    1893              :   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
    1894              : 
    1895              :   Bstatement*
    1896            0 :   do_get_backend(Translate_context*)
    1897            0 :   { go_unreachable(); }
    1898              : 
    1899              :   void
    1900              :   do_dump_statement(Ast_dump_context*) const;
    1901              : 
    1902              :  private:
    1903              :   // Lvalue which receives the value from the channel.
    1904              :   Expression* val_;
    1905              :   // Lvalue which receives whether the channel is closed.
    1906              :   Expression* closed_;
    1907              :   // The channel on which we receive the value.
    1908              :   Expression* channel_;
    1909              : };
    1910              : 
    1911              : // Traversal.
    1912              : 
    1913              : int
    1914          505 : Tuple_receive_assignment_statement::do_traverse(Traverse* traverse)
    1915              : {
    1916          505 :   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
    1917          505 :       || this->traverse_expression(traverse, &this->closed_) == TRAVERSE_EXIT)
    1918            0 :     return TRAVERSE_EXIT;
    1919          505 :   return this->traverse_expression(traverse, &this->channel_);
    1920              : }
    1921              : 
    1922              : void
    1923          287 : Tuple_receive_assignment_statement::do_determine_types(Gogo* gogo)
    1924              : {
    1925          287 :   this->val_->determine_type_no_context(gogo);
    1926          287 :   this->closed_->determine_type_no_context(gogo);
    1927          287 :   this->channel_->determine_type_no_context(gogo);
    1928          287 : }
    1929              : 
    1930              : void
    1931           80 : Tuple_receive_assignment_statement::do_check_types(Gogo*)
    1932              : {
    1933           80 :   Channel_type* ct = this->channel_->type()->channel_type();
    1934           80 :   if (ct == NULL)
    1935              :     {
    1936            0 :       this->report_error(_("expected channel"));
    1937            0 :       return;
    1938              :     }
    1939           80 :   if (!ct->may_receive())
    1940              :     {
    1941            1 :       this->report_error(_("invalid receive on send-only channel"));
    1942            1 :       return;
    1943              :     }
    1944              : 
    1945           79 :   if (!Assignment_statement::check_assignment_types(this->val_,
    1946              :                                                     ct->element_type(),
    1947              :                                                     this->location()))
    1948            0 :     this->set_is_error();
    1949           79 :   if (!Assignment_statement::check_assignment_types(this->closed_,
    1950              :                                                     Type::make_boolean_type(),
    1951              :                                                     this->location()))
    1952            0 :     this->set_is_error();
    1953              : }
    1954              : 
    1955              : // Lower to a function call.
    1956              : 
    1957              : Statement*
    1958          185 : Tuple_receive_assignment_statement::do_lower(Gogo* gogo, Named_object*,
    1959              :                                              Block* enclosing,
    1960              :                                              Statement_inserter*)
    1961              : {
    1962          185 :   Location loc = this->location();
    1963              : 
    1964          185 :   if (this->classification() == STATEMENT_ERROR)
    1965            0 :     return Statement::make_error_statement(loc);
    1966              : 
    1967          185 :   Channel_type* channel_type = this->channel_->type()->channel_type();
    1968          185 :   go_assert(channel_type != NULL && channel_type->may_receive());
    1969              : 
    1970          185 :   Block* b = new Block(enclosing, loc);
    1971              : 
    1972              :   // Make sure that any subexpressions on the left hand side are
    1973              :   // evaluated in the right order.
    1974          185 :   Move_ordered_evals moe(b);
    1975          185 :   this->val_->traverse_subexpressions(&moe);
    1976          185 :   this->closed_->traverse_subexpressions(&moe);
    1977              : 
    1978              :   // var val_temp ELEMENT_TYPE
    1979          185 :   Temporary_statement* val_temp =
    1980          185 :     Statement::make_temporary(channel_type->element_type(), NULL, loc);
    1981          185 :   b->add_statement(val_temp);
    1982              : 
    1983              :   // var closed_temp bool
    1984          185 :   Temporary_statement* closed_temp =
    1985          370 :     Statement::make_temporary((this->closed_->type()->is_boolean_type()
    1986          182 :                                ? this->closed_->type()
    1987            3 :                                : Type::lookup_bool_type()),
    1988              :                               NULL, loc);
    1989          185 :   b->add_statement(closed_temp);
    1990              : 
    1991              :   // closed_temp = chanrecv2(channel, &val_temp)
    1992          185 :   Temporary_reference_expression* ref =
    1993          185 :     Expression::make_temporary_reference(val_temp, loc);
    1994          185 :   Expression* p2 = Expression::make_unary(OPERATOR_AND, ref, loc);
    1995          185 :   Expression* call = Runtime::make_call(gogo, Runtime::CHANRECV2,
    1996              :                                         loc, 2, this->channel_, p2);
    1997          185 :   ref = Expression::make_temporary_reference(closed_temp, loc);
    1998          185 :   ref->set_is_lvalue();
    1999          185 :   Statement* s = Statement::make_assignment(ref, call, loc);
    2000          185 :   s->determine_types(gogo);
    2001          185 :   b->add_statement(s);
    2002              : 
    2003              :   // val = val_temp
    2004          185 :   ref = Expression::make_temporary_reference(val_temp, loc);
    2005          185 :   s = Statement::make_assignment(this->val_, ref, loc);
    2006          185 :   s->determine_types(gogo);
    2007          185 :   b->add_statement(s);
    2008              : 
    2009              :   // closed = closed_temp
    2010          185 :   ref = Expression::make_temporary_reference(closed_temp, loc);
    2011          185 :   s = Statement::make_assignment(this->closed_, ref, loc);
    2012          185 :   s->determine_types(gogo);
    2013          185 :   b->add_statement(s);
    2014              : 
    2015          185 :   return Statement::make_block_statement(b, loc);
    2016          185 : }
    2017              : 
    2018              : // Dump the AST representation for a tuple receive statement.
    2019              : 
    2020              : void
    2021            0 : Tuple_receive_assignment_statement::do_dump_statement(
    2022              :     Ast_dump_context* ast_dump_context) const
    2023              : {
    2024            0 :   ast_dump_context->print_indent();
    2025            0 :   ast_dump_context->dump_expression(this->val_);
    2026            0 :   ast_dump_context->ostream() << ", ";
    2027            0 :   ast_dump_context->dump_expression(this->closed_);
    2028            0 :   ast_dump_context->ostream() << " <- ";
    2029            0 :   ast_dump_context->dump_expression(this->channel_);
    2030            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    2031            0 : }
    2032              : 
    2033              : // Make a nonblocking receive statement.
    2034              : 
    2035              : Statement*
    2036          186 : Statement::make_tuple_receive_assignment(Expression* val, Expression* closed,
    2037              :                                          Expression* channel,
    2038              :                                          Location location)
    2039              : {
    2040          186 :   return new Tuple_receive_assignment_statement(val, closed, channel,
    2041          186 :                                                 location);
    2042              : }
    2043              : 
    2044              : // An assignment to a pair of values from a type guard.  This is a
    2045              : // conditional type guard.  v, ok = i.(type).
    2046              : 
    2047              : class Tuple_type_guard_assignment_statement : public Statement
    2048              : {
    2049              :  public:
    2050         6693 :   Tuple_type_guard_assignment_statement(Expression* val, Expression* ok,
    2051              :                                         Expression* expr, Type* type,
    2052              :                                         Location location)
    2053         6693 :     : Statement(STATEMENT_TUPLE_TYPE_GUARD_ASSIGNMENT, location),
    2054        13386 :       val_(val), ok_(ok), expr_(expr), type_(type)
    2055              :   { }
    2056              : 
    2057              :  protected:
    2058              :   int
    2059              :   do_traverse(Traverse*);
    2060              : 
    2061              :   void
    2062              :   do_determine_types(Gogo*);
    2063              : 
    2064              :   void
    2065              :   do_check_types(Gogo*);
    2066              : 
    2067              :   Statement*
    2068              :   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
    2069              : 
    2070              :   Bstatement*
    2071            0 :   do_get_backend(Translate_context*)
    2072            0 :   { go_unreachable(); }
    2073              : 
    2074              :   void
    2075              :   do_dump_statement(Ast_dump_context*) const;
    2076              : 
    2077              :  private:
    2078              :   Call_expression*
    2079              :   lower_to_type(Gogo*, Runtime::Function);
    2080              : 
    2081              :   void
    2082              :   lower_to_object_type(Gogo*, Block*, Runtime::Function);
    2083              : 
    2084              :   // The variable which recieves the converted value.
    2085              :   Expression* val_;
    2086              :   // The variable which receives the indication of success.
    2087              :   Expression* ok_;
    2088              :   // The expression being converted.
    2089              :   Expression* expr_;
    2090              :   // The type to which the expression is being converted.
    2091              :   Type* type_;
    2092              : };
    2093              : 
    2094              : // Traverse a type guard tuple assignment.
    2095              : 
    2096              : int
    2097        33464 : Tuple_type_guard_assignment_statement::do_traverse(Traverse* traverse)
    2098              : {
    2099        33464 :   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT
    2100        33464 :       || this->traverse_expression(traverse, &this->ok_) == TRAVERSE_EXIT
    2101        66928 :       || this->traverse_type(traverse, this->type_) == TRAVERSE_EXIT)
    2102            0 :     return TRAVERSE_EXIT;
    2103        33464 :   return this->traverse_expression(traverse, &this->expr_);
    2104              : }
    2105              : 
    2106              : void
    2107         6693 : Tuple_type_guard_assignment_statement::do_determine_types(Gogo* gogo)
    2108              : {
    2109         6693 :   this->val_->determine_type_no_context(gogo);
    2110         6693 :   this->ok_->determine_type_no_context(gogo);
    2111         6693 :   this->expr_->determine_type_no_context(gogo);
    2112         6693 : }
    2113              : 
    2114              : void
    2115         6693 : Tuple_type_guard_assignment_statement::do_check_types(Gogo*)
    2116              : {
    2117         6693 :   Type* expr_type = this->expr_->type();
    2118         6693 :   if (expr_type->interface_type() == NULL)
    2119              :     {
    2120            0 :       if (!expr_type->is_error() && !this->type_->is_error())
    2121            0 :         this->report_error(_("type assertion only valid for interface types"));
    2122            0 :       return;
    2123              :     }
    2124              : 
    2125         6693 :   if (!Assignment_statement::check_assignment_types(this->val_, this->type_,
    2126              :                                                     this->location()))
    2127            1 :     this->set_is_error();
    2128         6693 :   if (!Assignment_statement::check_assignment_types(this->ok_,
    2129              :                                                     Type::make_boolean_type(),
    2130              :                                                     this->location()))
    2131            0 :     this->set_is_error();
    2132              : }
    2133              : 
    2134              : // Lower to a function call.
    2135              : 
    2136              : Statement*
    2137         6692 : Tuple_type_guard_assignment_statement::do_lower(Gogo* gogo, Named_object*,
    2138              :                                                 Block* enclosing,
    2139              :                                                 Statement_inserter*)
    2140              : {
    2141         6692 :   Location loc = this->location();
    2142              : 
    2143         6692 :   if (this->classification() == STATEMENT_ERROR)
    2144            0 :     return Statement::make_error_statement(loc);
    2145              : 
    2146         6692 :   Type* expr_type = this->expr_->type();
    2147         6692 :   go_assert(expr_type->interface_type() != NULL);
    2148              : 
    2149         6692 :   Block* b = new Block(enclosing, loc);
    2150              : 
    2151              :   // Make sure that any subexpressions on the left hand side are
    2152              :   // evaluated in the right order.
    2153         6692 :   Move_ordered_evals moe(b);
    2154         6692 :   this->val_->traverse_subexpressions(&moe);
    2155         6692 :   this->ok_->traverse_subexpressions(&moe);
    2156              : 
    2157        13384 :   bool expr_is_empty = expr_type->interface_type()->is_empty();
    2158         6692 :   Call_expression* call;
    2159         6692 :   if (this->type_->interface_type() != NULL)
    2160              :     {
    2161         2684 :       if (this->type_->interface_type()->is_empty())
    2162           20 :         call = Runtime::make_call(gogo,
    2163              :                                   (expr_is_empty
    2164              :                                    ? Runtime::IFACEE2E2
    2165              :                                    : Runtime::IFACEI2E2),
    2166              :                                   loc, 1, this->expr_);
    2167              :       else
    2168         2362 :         call = this->lower_to_type(gogo,
    2169              :                                    (expr_is_empty
    2170              :                                     ? Runtime::IFACEE2I2
    2171              :                                     : Runtime::IFACEI2I2));
    2172              :     }
    2173         5350 :   else if (this->type_->points_to() != NULL)
    2174         7610 :     call = this->lower_to_type(gogo,
    2175              :                                (expr_is_empty
    2176              :                                 ? Runtime::IFACEE2T2P
    2177              :                                 : Runtime::IFACEI2T2P));
    2178              :   else
    2179              :     {
    2180         1300 :       this->lower_to_object_type(gogo, b,
    2181              :                                  (expr_is_empty
    2182              :                                   ? Runtime::IFACEE2T2
    2183              :                                   : Runtime::IFACEI2T2));
    2184         1300 :       call = NULL;
    2185              :     }
    2186              : 
    2187         6692 :   if (call != NULL)
    2188              :     {
    2189         5392 :       Expression* res = Expression::make_call_result(call, 0);
    2190         5392 :       res = Expression::make_unsafe_cast(this->type_, res, loc);
    2191         5392 :       Statement* s = Statement::make_assignment(this->val_, res, loc);
    2192         5392 :       s->determine_types(gogo);
    2193         5392 :       b->add_statement(s);
    2194              : 
    2195         5392 :       res = Expression::make_call_result(call, 1);
    2196         5392 :       if (!this->ok_->type()->is_boolean_type())
    2197         1209 :         res = Expression::make_cast(Type::lookup_bool_type(), res, loc);
    2198         5392 :       s = Statement::make_assignment(this->ok_, res, loc);
    2199         5392 :       s->determine_types(gogo);
    2200         5392 :       b->add_statement(s);
    2201              :     }
    2202              : 
    2203         6692 :   return Statement::make_block_statement(b, loc);
    2204         6692 : }
    2205              : 
    2206              : // Lower a conversion to a non-empty interface type or a pointer type.
    2207              : 
    2208              : Call_expression*
    2209         5378 : Tuple_type_guard_assignment_statement::lower_to_type(Gogo* gogo,
    2210              :                                                      Runtime::Function code)
    2211              : {
    2212         5378 :   Location loc = this->location();
    2213         5378 :   return Runtime::make_call(gogo, code, loc, 2,
    2214              :                             Expression::make_type_descriptor(this->type_, loc),
    2215         5378 :                             this->expr_);
    2216              : }
    2217              : 
    2218              : // Lower a conversion to a non-interface non-pointer type.
    2219              : 
    2220              : void
    2221         1300 : Tuple_type_guard_assignment_statement::lower_to_object_type(
    2222              :     Gogo* gogo,
    2223              :     Block* b,
    2224              :     Runtime::Function code)
    2225              : {
    2226         1300 :   Location loc = this->location();
    2227              : 
    2228              :   // var val_temp TYPE
    2229         1300 :   Temporary_statement* val_temp = Statement::make_temporary(this->type_,
    2230              :                                                             NULL, loc);
    2231         1300 :   b->add_statement(val_temp);
    2232              : 
    2233              :   // var ok_temp bool
    2234         1300 :   Temporary_statement* ok_temp = NULL;
    2235         1300 :   if (!this->ok_->is_sink_expression())
    2236              :     {
    2237         1924 :       ok_temp = Statement::make_temporary((this->ok_->type()->is_boolean_type()
    2238          962 :                                            ? this->ok_->type()
    2239            0 :                                            : Type::lookup_bool_type()),
    2240              :                                           NULL, loc);
    2241          962 :       b->add_statement(ok_temp);
    2242              :     }
    2243              : 
    2244              :   // ok_temp = CODE(type_descriptor, expr, &val_temp)
    2245         1300 :   Expression* p1 = Expression::make_type_descriptor(this->type_, loc);
    2246         1300 :   Expression* ref = Expression::make_temporary_reference(val_temp, loc);
    2247         1300 :   Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
    2248         1300 :   Expression* call = Runtime::make_call(gogo, code, loc, 3,
    2249              :                                         p1, this->expr_, p3);
    2250         1300 :   Statement* s;
    2251         1300 :   if (ok_temp == NULL)
    2252          338 :     s = Statement::make_statement(call, true);
    2253              :   else
    2254              :     {
    2255          962 :       Expression* ok_ref = Expression::make_temporary_reference(ok_temp, loc);
    2256          962 :       s = Statement::make_assignment(ok_ref, call, loc);
    2257              :     }
    2258         1300 :   s->determine_types(gogo);
    2259         1300 :   b->add_statement(s);
    2260              : 
    2261              :   // val = val_temp
    2262         1300 :   ref = Expression::make_temporary_reference(val_temp, loc);
    2263         1300 :   s = Statement::make_assignment(this->val_, ref, loc);
    2264         1300 :   s->determine_types(gogo);
    2265         1300 :   b->add_statement(s);
    2266              : 
    2267              :   // ok = ok_temp
    2268         1300 :   if (ok_temp != NULL)
    2269              :     {
    2270          962 :       ref = Expression::make_temporary_reference(ok_temp, loc);
    2271          962 :       s = Statement::make_assignment(this->ok_, ref, loc);
    2272          962 :       s->determine_types(gogo);
    2273          962 :       b->add_statement(s);
    2274              :     }
    2275         1300 : }
    2276              : 
    2277              : // Dump the AST representation for a tuple type guard statement.
    2278              : 
    2279              : void
    2280            0 : Tuple_type_guard_assignment_statement::do_dump_statement(
    2281              :     Ast_dump_context* ast_dump_context) const
    2282              : {
    2283            0 :   ast_dump_context->print_indent();
    2284            0 :   ast_dump_context->dump_expression(this->val_);
    2285            0 :   ast_dump_context->ostream() << ", ";
    2286            0 :   ast_dump_context->dump_expression(this->ok_);
    2287            0 :   ast_dump_context->ostream() << " = ";
    2288            0 :   ast_dump_context->dump_expression(this->expr_);
    2289            0 :   ast_dump_context->ostream() << " . ";
    2290            0 :   ast_dump_context->dump_type(this->type_);
    2291            0 :   ast_dump_context->ostream()  << dsuffix(location()) << std::endl;
    2292            0 : }
    2293              : 
    2294              : // Make an assignment from a type guard to a pair of variables.
    2295              : 
    2296              : Statement*
    2297         6693 : Statement::make_tuple_type_guard_assignment(Expression* val, Expression* ok,
    2298              :                                             Expression* expr, Type* type,
    2299              :                                             Location location)
    2300              : {
    2301         6693 :   return new Tuple_type_guard_assignment_statement(val, ok, expr, type,
    2302         6693 :                                                    location);
    2303              : }
    2304              : 
    2305              : // Class Expression_statement.
    2306              : 
    2307              : // Constructor.
    2308              : 
    2309       829784 : Expression_statement::Expression_statement(Expression* expr, bool is_ignored)
    2310              :   : Statement(STATEMENT_EXPRESSION, expr->location()),
    2311       829784 :     expr_(expr), is_ignored_(is_ignored)
    2312              : {
    2313       829784 : }
    2314              : 
    2315              : // Determine types.
    2316              : 
    2317              : void
    2318       765202 : Expression_statement::do_determine_types(Gogo* gogo)
    2319              : {
    2320       765202 :   this->expr_->determine_type_no_context(gogo);
    2321       765202 : }
    2322              : 
    2323              : // Check the types of an expression statement.  The only check we do
    2324              : // is to possibly give an error about discarding the value of the
    2325              : // expression.
    2326              : 
    2327              : void
    2328       259468 : Expression_statement::do_check_types(Gogo*)
    2329              : {
    2330       259468 :   if (!this->is_ignored_)
    2331       251818 :     this->expr_->discarding_value();
    2332       259468 : }
    2333              : 
    2334              : // An expression statement is only a terminating statement if it is
    2335              : // a call to panic.
    2336              : 
    2337              : bool
    2338         1239 : Expression_statement::do_may_fall_through() const
    2339              : {
    2340              :   // The builtin function panic does not return.
    2341         1308 :   const Call_expression* call = this->expr_->call_expression();
    2342         1239 :   if (call == NULL)
    2343              :     return true;
    2344         1239 :   const Builtin_call_expression* bce = call->builtin_call_expression();
    2345         1228 :   return bce == NULL || bce->code() != Builtin_call_expression::BUILTIN_PANIC;
    2346              : }
    2347              : 
    2348              : // Export an expression statement.
    2349              : 
    2350              : void
    2351         4909 : Expression_statement::do_export_statement(Export_function_body* efb)
    2352              : {
    2353         4909 :   this->expr_->export_expression(efb);
    2354         4909 : }
    2355              : 
    2356              : // Convert to backend representation.
    2357              : 
    2358              : Bstatement*
    2359       823920 : Expression_statement::do_get_backend(Translate_context* context)
    2360              : {
    2361       823920 :   Bexpression* bexpr = this->expr_->get_backend(context);
    2362       823920 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    2363       823920 :   return context->backend()->expression_statement(bfunction, bexpr);
    2364              : }
    2365              : 
    2366              : // Dump the AST representation for an expression statement
    2367              : 
    2368              : void
    2369            0 : Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    2370              :     const
    2371              : {
    2372            0 :   ast_dump_context->print_indent();
    2373            0 :   ast_dump_context->dump_expression(expr_);
    2374            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    2375            0 : }
    2376              : 
    2377              : // Make an expression statement from an Expression.
    2378              : 
    2379              : Statement*
    2380       829784 : Statement::make_statement(Expression* expr, bool is_ignored)
    2381              : {
    2382       829784 :   return new Expression_statement(expr, is_ignored);
    2383              : }
    2384              : 
    2385              : // Export data for a block.
    2386              : 
    2387              : void
    2388        22817 : Block_statement::do_export_statement(Export_function_body* efb)
    2389              : {
    2390        22817 :   Block_statement::export_block(efb, this->block_,
    2391        22817 :                                 this->is_lowered_for_statement_);
    2392        22817 : }
    2393              : 
    2394              : void
    2395        27416 : Block_statement::export_block(Export_function_body* efb, Block* block,
    2396              :                               bool is_lowered_for_statement)
    2397              : {
    2398              :   // We are already indented to the right position.
    2399        27416 :   char buf[50];
    2400        27416 :   efb->write_c_string("{");
    2401        27416 :   if (is_lowered_for_statement)
    2402          445 :     efb->write_c_string(" /*for*/");
    2403        27416 :   snprintf(buf, sizeof buf, " //%d\n",
    2404              :            Linemap::location_to_line(block->start_location()));
    2405        27416 :   efb->write_c_string(buf);
    2406              : 
    2407        27416 :   block->export_block(efb);
    2408              :   // The indentation is correct for the statements in the block, so
    2409              :   // subtract one for the closing curly brace.
    2410        27416 :   efb->decrement_indent();
    2411        27416 :   efb->indent();
    2412        27416 :   efb->write_c_string("}");
    2413              :   // Increment back to the value the caller thinks it has.
    2414        27416 :   efb->increment_indent();
    2415        27416 : }
    2416              : 
    2417              : // Import a block statement, returning the block.
    2418              : 
    2419              : Block*
    2420        26622 : Block_statement::do_import(Import_function_body* ifb, Location loc,
    2421              :                            bool* is_lowered_for_statement)
    2422              : {
    2423        26622 :   go_assert(ifb->match_c_string("{"));
    2424        26622 :   *is_lowered_for_statement = false;
    2425        26622 :   if (ifb->match_c_string(" /*for*/"))
    2426              :     {
    2427            0 :       ifb->advance(8);
    2428            0 :       *is_lowered_for_statement = true;
    2429              :     }
    2430        26622 :   size_t nl = ifb->body().find('\n', ifb->off());
    2431        26622 :   if (nl == std::string::npos)
    2432              :     {
    2433            0 :       if (!ifb->saw_error())
    2434            0 :         go_error_at(ifb->location(),
    2435              :                     "import error: no newline after %<{%> at %lu",
    2436            0 :                     static_cast<unsigned long>(ifb->off()));
    2437            0 :       ifb->set_saw_error();
    2438            0 :       return NULL;
    2439              :     }
    2440        26622 :   ifb->set_off(nl + 1);
    2441        26622 :   ifb->increment_indent();
    2442        26622 :   Block* block = new Block(ifb->block(), loc);
    2443        26622 :   ifb->begin_block(block);
    2444        26622 :   bool ok = Block::import_block(block, ifb, loc);
    2445        26622 :   ifb->finish_block();
    2446        26622 :   ifb->decrement_indent();
    2447        26622 :   if (!ok)
    2448              :     return NULL;
    2449              :   return block;
    2450              : }
    2451              : 
    2452              : // Convert a block to the backend representation of a statement.
    2453              : 
    2454              : Bstatement*
    2455      1359964 : Block_statement::do_get_backend(Translate_context* context)
    2456              : {
    2457      1359964 :   Bblock* bblock = this->block_->get_backend(context);
    2458      1359964 :   return context->backend()->block_statement(bblock);
    2459              : }
    2460              : 
    2461              : // Dump the AST for a block statement
    2462              : 
    2463              : void
    2464            0 : Block_statement::do_dump_statement(Ast_dump_context*) const
    2465              : {
    2466              :   // block statement braces are dumped when traversing.
    2467            0 : }
    2468              : 
    2469              : // Make a block statement.
    2470              : 
    2471              : Block_statement*
    2472      1363149 : Statement::make_block_statement(Block* block, Location location)
    2473              : {
    2474      1363149 :   return new Block_statement(block, location);
    2475              : }
    2476              : 
    2477              : // An increment or decrement statement.
    2478              : 
    2479              : class Inc_dec_statement : public Statement
    2480              : {
    2481              :  public:
    2482        58820 :   Inc_dec_statement(bool is_inc, Expression* expr)
    2483        58820 :     : Statement(STATEMENT_INCDEC, expr->location()),
    2484       117640 :       expr_(expr), is_inc_(is_inc)
    2485              :   { }
    2486              : 
    2487              :  protected:
    2488              :   int
    2489       168631 :   do_traverse(Traverse* traverse)
    2490       168631 :   { return this->traverse_expression(traverse, &this->expr_); }
    2491              : 
    2492              :   void
    2493              :   do_determine_types(Gogo*);
    2494              : 
    2495              :   void
    2496              :   do_check_types(Gogo*);
    2497              : 
    2498              :   Statement*
    2499              :   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
    2500              : 
    2501              :   Bstatement*
    2502            0 :   do_get_backend(Translate_context*)
    2503            0 :   { go_unreachable(); }
    2504              : 
    2505              :   void
    2506              :   do_dump_statement(Ast_dump_context*) const;
    2507              : 
    2508              :  private:
    2509              :   // The l-value to increment or decrement.
    2510              :   Expression* expr_;
    2511              :   // Whether to increment or decrement.
    2512              :   bool is_inc_;
    2513              : };
    2514              : 
    2515              : void
    2516        90187 : Inc_dec_statement::do_determine_types(Gogo* gogo)
    2517              : {
    2518        90187 :   this->expr_->determine_type_no_context(gogo);
    2519        90187 : }
    2520              : 
    2521              : void
    2522        27453 : Inc_dec_statement::do_check_types(Gogo*)
    2523              : {
    2524        27453 :   if (!this->expr_->is_addressable()
    2525        27453 :       && !Index_expression::is_map_index(this->expr_))
    2526              :     {
    2527            0 :       if (!this->expr_->type()->is_error())
    2528            0 :         this->report_error(_("invalid left hand side of assignment"));
    2529            0 :       this->set_is_error();
    2530            0 :       return;
    2531              :     }
    2532        27453 :   if (!this->expr_->type()->is_numeric_type())
    2533              :     {
    2534            1 :       this->report_error(_("increment or decrement of non-numeric type"));
    2535            1 :       return;
    2536              :     }
    2537              : }
    2538              : 
    2539              : // Lower to += or -=.
    2540              : 
    2541              : Statement*
    2542        58819 : Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
    2543              : {
    2544        58819 :   Location loc = this->location();
    2545        58819 :   Expression* oexpr = Expression::make_integer_ul(1, this->expr_->type(), loc);
    2546        58819 :   Operator op = this->is_inc_ ? OPERATOR_PLUSEQ : OPERATOR_MINUSEQ;
    2547        58819 :   return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
    2548              : }
    2549              : 
    2550              : // Dump the AST representation for a inc/dec statement.
    2551              : 
    2552              : void
    2553            0 : Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    2554              : {
    2555            0 :   ast_dump_context->print_indent();
    2556            0 :   ast_dump_context->dump_expression(expr_);
    2557            0 :   ast_dump_context->ostream() << (is_inc_? "++": "--") << dsuffix(location()) << std::endl;
    2558            0 : }
    2559              : 
    2560              : // Make an increment statement.
    2561              : 
    2562              : Statement*
    2563        54549 : Statement::make_inc_statement(Expression* expr)
    2564              : {
    2565        54549 :   return new Inc_dec_statement(true, expr);
    2566              : }
    2567              : 
    2568              : // Make a decrement statement.
    2569              : 
    2570              : Statement*
    2571         4271 : Statement::make_dec_statement(Expression* expr)
    2572              : {
    2573         4271 :   return new Inc_dec_statement(false, expr);
    2574              : }
    2575              : 
    2576              : // Class Thunk_statement.  This is the base class for go and defer
    2577              : // statements.
    2578              : 
    2579              : // Constructor.
    2580              : 
    2581        27523 : Thunk_statement::Thunk_statement(Statement_classification classification,
    2582              :                                  Call_expression* call,
    2583        27523 :                                  Location location)
    2584              :     : Statement(classification, location),
    2585        27523 :       call_(call)
    2586              : {
    2587        27523 : }
    2588              : 
    2589              : // Return whether this is a simple statement which does not require a
    2590              : // thunk.
    2591              : 
    2592              : bool
    2593        13743 : Thunk_statement::is_simple(Function_type* fntype) const
    2594              : {
    2595              :   // We need a thunk to call a method, or to pass a variable number of
    2596              :   // arguments.
    2597        13743 :   if (fntype->is_method() || fntype->is_varargs())
    2598              :     return false;
    2599              : 
    2600              :   // A defer statement requires a thunk to set up for whether the
    2601              :   // function can call recover.
    2602        13432 :   if (this->classification() == STATEMENT_DEFER)
    2603              :     return false;
    2604              : 
    2605              :   // We can only permit a single parameter of pointer type.
    2606         2501 :   const Typed_identifier_list* parameters = fntype->parameters();
    2607         2501 :   if (parameters != NULL
    2608         3325 :       && (parameters->size() > 1
    2609          403 :           || (parameters->size() == 1
    2610          403 :               && parameters->begin()->type()->points_to() == NULL)))
    2611          771 :     return false;
    2612              : 
    2613              :   // If the function returns multiple values, or returns a type other
    2614              :   // than integer, floating point, or pointer, then it may get a
    2615              :   // hidden first parameter, in which case we need the more
    2616              :   // complicated approach.  This is true even though we are going to
    2617              :   // ignore the return value.
    2618         1730 :   const Typed_identifier_list* results = fntype->results();
    2619         1730 :   if (results != NULL
    2620         1755 :       && (results->size() > 1
    2621           25 :           || (results->size() == 1
    2622           25 :               && !results->begin()->type()->is_basic_type()
    2623           24 :               && results->begin()->type()->points_to() == NULL)))
    2624           24 :     return false;
    2625              : 
    2626              :   // If this calls something that is not a simple function, then we
    2627              :   // need a thunk.
    2628         1706 :   Expression* fn = this->call_->call_expression()->fn();
    2629        15200 :   if (fn->func_expression() == NULL)
    2630              :     return false;
    2631              : 
    2632              :   // If the function uses a closure, then we need a thunk.  FIXME: We
    2633              :   // could accept a zero argument function with a closure.
    2634         1559 :   if (fn->func_expression()->closure() != NULL)
    2635              :     return false;
    2636              : 
    2637              :   return true;
    2638              : }
    2639              : 
    2640              : // Traverse a thunk statement.
    2641              : 
    2642              : int
    2643       328818 : Thunk_statement::do_traverse(Traverse* traverse)
    2644              : {
    2645       328818 :   return this->traverse_expression(traverse, &this->call_);
    2646              : }
    2647              : 
    2648              : // Determine types in a thunk statement.
    2649              : 
    2650              : void
    2651        27901 : Thunk_statement::do_determine_types(Gogo* gogo)
    2652              : {
    2653        27901 :   this->call_->determine_type_no_context(gogo);
    2654        27901 : }
    2655              : 
    2656              : // Check types in a thunk statement.
    2657              : 
    2658              : void
    2659        27523 : Thunk_statement::do_check_types(Gogo*)
    2660              : {
    2661        27523 :   if (!this->call_->discarding_value())
    2662              :     {
    2663           42 :       this->set_is_error();
    2664           42 :       return;
    2665              :     }
    2666        27481 :   Call_expression* ce = this->call_->call_expression();
    2667            2 :   if (ce == NULL)
    2668              :     {
    2669            2 :       if (!this->call_->is_error_expression())
    2670            0 :         this->report_error("expected call expression");
    2671            2 :       this->set_is_error();
    2672            2 :       return;
    2673              :     }
    2674              : }
    2675              : 
    2676              : // The Traverse class used to find and simplify thunk statements.
    2677              : 
    2678         9292 : class Simplify_thunk_traverse : public Traverse
    2679              : {
    2680              :  public:
    2681         4646 :   Simplify_thunk_traverse(Gogo* gogo)
    2682         4646 :     : Traverse(traverse_functions | traverse_blocks),
    2683         4646 :       gogo_(gogo), function_(NULL)
    2684              :   { }
    2685              : 
    2686              :   int
    2687              :   function(Named_object*);
    2688              : 
    2689              :   int
    2690              :   block(Block*);
    2691              : 
    2692              :  private:
    2693              :   // General IR.
    2694              :   Gogo* gogo_;
    2695              :   // The function we are traversing.
    2696              :   Named_object* function_;
    2697              : };
    2698              : 
    2699              : // Keep track of the current function while looking for thunks.
    2700              : 
    2701              : int
    2702       203075 : Simplify_thunk_traverse::function(Named_object* no)
    2703              : {
    2704       203075 :   go_assert(this->function_ == NULL);
    2705       203075 :   this->function_ = no;
    2706       203075 :   int t = no->func_value()->traverse(this);
    2707       203075 :   this->function_ = NULL;
    2708       203075 :   if (t == TRAVERSE_EXIT)
    2709            0 :     return t;
    2710              :   return TRAVERSE_SKIP_COMPONENTS;
    2711              : }
    2712              : 
    2713              : // Look for thunks in a block.
    2714              : 
    2715              : int
    2716      1722684 : Simplify_thunk_traverse::block(Block* b)
    2717              : {
    2718              :   // The parser ensures that thunk statements always appear at the end
    2719              :   // of a block.
    2720      1722684 :   if (b->statements()->size() < 1)
    2721              :     return TRAVERSE_CONTINUE;
    2722      1718069 :   Thunk_statement* stat = b->statements()->back()->thunk_statement();
    2723      1718069 :   if (stat == NULL)
    2724              :     return TRAVERSE_CONTINUE;
    2725        13743 :   if (stat->simplify_statement(this->gogo_, this->function_, b))
    2726              :     return TRAVERSE_SKIP_COMPONENTS;
    2727              :   return TRAVERSE_CONTINUE;
    2728              : }
    2729              : 
    2730              : // Simplify all thunk statements.
    2731              : 
    2732              : void
    2733         4646 : Gogo::simplify_thunk_statements()
    2734              : {
    2735         4646 :   Simplify_thunk_traverse thunk_traverse(this);
    2736         4646 :   this->traverse(&thunk_traverse);
    2737         4646 : }
    2738              : 
    2739              : // Return true if the thunk function is a constant, which means that
    2740              : // it does not need to be passed to the thunk routine.
    2741              : 
    2742              : bool
    2743        40923 : Thunk_statement::is_constant_function() const
    2744              : {
    2745        40923 :   Call_expression* ce = this->call_->call_expression();
    2746        40923 :   Function_type* fntype = ce->get_function_type();
    2747        40923 :   if (fntype == NULL)
    2748              :     {
    2749            0 :       go_assert(saw_errors());
    2750              :       return false;
    2751              :     }
    2752        40923 :   if (fntype->is_builtin())
    2753              :     return true;
    2754        39930 :   Expression* fn = ce->fn();
    2755        39930 :   if (fn->func_expression() != NULL)
    2756        18543 :     return fn->func_expression()->closure() == NULL;
    2757        21387 :   if (fn->interface_field_reference_expression() != NULL)
    2758              :     return true;
    2759        18645 :   if (fn->bound_method_expression() != NULL)
    2760              :     return true;
    2761              :   return false;
    2762              : }
    2763              : 
    2764              : // Simplify complex thunk statements into simple ones.  A complicated
    2765              : // thunk statement is one which takes anything other than zero
    2766              : // parameters or a single pointer parameter.  We rewrite it into code
    2767              : // which allocates a struct, stores the parameter values into the
    2768              : // struct, and does a simple go or defer statement which passes the
    2769              : // struct to a thunk.  The thunk does the real call.
    2770              : 
    2771              : bool
    2772        13743 : Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
    2773              :                                     Block* block)
    2774              : {
    2775        13743 :   if (this->classification() == STATEMENT_ERROR)
    2776              :     return false;
    2777        13743 :   if (this->call_->is_error_expression())
    2778              :     return false;
    2779              : 
    2780        13743 :   if (this->classification() == STATEMENT_DEFER)
    2781              :     {
    2782              :       // Make sure that the defer stack exists for the function.  We
    2783              :       // will use when converting this statement to the backend
    2784              :       // representation, but we want it to exist when we start
    2785              :       // converting the function.
    2786        11230 :       function->func_value()->defer_stack(this->location());
    2787              :     }
    2788              : 
    2789        13743 :   Call_expression* ce = this->call_->call_expression();
    2790        13743 :   Function_type* fntype = ce->get_function_type();
    2791        13743 :   if (fntype == NULL)
    2792              :     {
    2793            0 :       go_assert(saw_errors());
    2794            0 :       this->set_is_error();
    2795            0 :       return false;
    2796              :     }
    2797        13743 :   if (this->is_simple(fntype))
    2798              :     return false;
    2799              : 
    2800        13641 :   Struct_type* struct_type = this->build_struct(fntype);
    2801              : 
    2802        13641 :   Expression* fn = ce->fn();
    2803        13641 :   Interface_field_reference_expression* interface_method =
    2804        13641 :     fn->interface_field_reference_expression();
    2805        13641 :   Bound_method_expression* bme = fn->bound_method_expression();
    2806              : 
    2807        13641 :   Location location = this->location();
    2808              : 
    2809        13641 :   bool is_constant_function = this->is_constant_function();
    2810        13641 :   Temporary_statement* fn_temp = NULL;
    2811        13641 :   if (!is_constant_function)
    2812              :     {
    2813         3781 :       fn_temp = Statement::make_temporary(NULL, fn, location);
    2814         3781 :       block->insert_statement_before(block->statements()->size() - 1, fn_temp);
    2815         3781 :       fn = Expression::make_temporary_reference(fn_temp, location);
    2816              :     }
    2817              : 
    2818        13641 :   std::string thunk_name = gogo->thunk_name();
    2819              : 
    2820              :   // Build the thunk.
    2821        13641 :   this->build_thunk(gogo, thunk_name, struct_type);
    2822              : 
    2823              :   // Generate code to call the thunk.
    2824              : 
    2825              :   // Get the values to store into the struct which is the single
    2826              :   // argument to the thunk.
    2827              : 
    2828        13641 :   Expression_list* vals = new Expression_list();
    2829        13641 :   if (!is_constant_function)
    2830         3781 :     vals->push_back(fn);
    2831              : 
    2832        13641 :   if (interface_method != NULL)
    2833          914 :     vals->push_back(interface_method->expr());
    2834        13641 :   if (bme != NULL)
    2835         5513 :     vals->push_back(bme->first_argument());
    2836              : 
    2837        13641 :   if (ce->args() != NULL)
    2838              :     {
    2839         8610 :       for (Expression_list::const_iterator p = ce->args()->begin();
    2840         8610 :            p != ce->args()->end();
    2841         4990 :            ++p)
    2842              :         {
    2843         4990 :           if ((*p)->is_constant())
    2844          499 :             continue;
    2845         4491 :           vals->push_back(*p);
    2846              :         }
    2847              :     }
    2848              : 
    2849              :   // Build the struct.
    2850        13641 :   Expression* constructor =
    2851        13641 :     Expression::make_struct_composite_literal(struct_type, vals, location);
    2852              : 
    2853              :   // Allocate the initialized struct on the heap.
    2854        13641 :   constructor = Expression::make_heap_expression(constructor, location);
    2855        13641 :   if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
    2856        10957 :     constructor->heap_expression()->set_allocate_on_stack();
    2857              : 
    2858              :   // Throw an error if the function is nil.  This is so that for `go
    2859              :   // nil` we get a backtrace from the go statement, rather than a
    2860              :   // useless backtrace from the brand new goroutine.
    2861        13641 :   Expression* param = constructor;
    2862        13641 :   if (!is_constant_function && this->classification() == STATEMENT_GO)
    2863              :     {
    2864         1758 :       fn = Expression::make_temporary_reference(fn_temp, location);
    2865         1758 :       Expression* nil = Expression::make_nil(location);
    2866         1758 :       Expression* isnil = Expression::make_binary(OPERATOR_EQEQ, fn, nil,
    2867              :                                                   location);
    2868         1758 :       Expression* crash = Runtime::make_call(gogo, Runtime::PANIC_GO_NIL,
    2869              :                                              location, 0);
    2870         1758 :       crash = Expression::make_conditional(isnil, crash,
    2871              :                                            Expression::make_nil(location),
    2872              :                                            location);
    2873         1758 :       param = Expression::make_compound(crash, constructor, location);
    2874              :     }
    2875              : 
    2876              :   // Look up the thunk.
    2877        13641 :   Named_object* named_thunk = gogo->lookup(thunk_name, NULL);
    2878        13641 :   go_assert(named_thunk != NULL && named_thunk->is_function());
    2879              : 
    2880              :   // Build the call.
    2881        13641 :   Expression* func = Expression::make_func_reference(named_thunk, NULL,
    2882              :                                                      location);
    2883        13641 :   Expression_list* params = new Expression_list();
    2884        13641 :   params->push_back(param);
    2885        13641 :   Call_expression* call = Expression::make_call(func, params, false, location);
    2886              : 
    2887              :   // Build the simple go or defer statement.
    2888        13641 :   Statement* s;
    2889        13641 :   if (this->classification() == STATEMENT_GO)
    2890         2411 :     s = Statement::make_go_statement(call, location);
    2891        11230 :   else if (this->classification() == STATEMENT_DEFER)
    2892              :     {
    2893        11230 :       s = Statement::make_defer_statement(call, location);
    2894        11230 :       if ((Node::make_node(this)->encoding() & ESCAPE_MASK) == Node::ESCAPE_NONE)
    2895        10957 :         s->defer_statement()->set_on_stack();
    2896              :     }
    2897              :   else
    2898            0 :     go_unreachable();
    2899              : 
    2900              :   // The current block should end with the go statement.
    2901        13641 :   go_assert(block->statements()->size() >= 1);
    2902        13641 :   go_assert(block->statements()->back() == this);
    2903        13641 :   block->replace_statement(block->statements()->size() - 1, s);
    2904              : 
    2905              :   // We already ran the determine_types pass, so we need to run it now
    2906              :   // for the new statement.
    2907        13641 :   s->determine_types(gogo);
    2908              : 
    2909              :   // Sanity check.
    2910        13641 :   gogo->check_types_in_block(block);
    2911              : 
    2912              :   // Return true to tell the block not to keep looking at statements.
    2913        13641 :   return true;
    2914        13641 : }
    2915              : 
    2916              : // Set the name to use for thunk parameter N.
    2917              : 
    2918              : void
    2919         4491 : Thunk_statement::thunk_field_param(int n, char* buf, size_t buflen)
    2920              : {
    2921         4491 :   snprintf(buf, buflen, "a%d", n);
    2922         4491 : }
    2923              : 
    2924              : // Build a new struct type to hold the parameters for a complicated
    2925              : // thunk statement.  FNTYPE is the type of the function call.
    2926              : 
    2927              : Struct_type*
    2928        13641 : Thunk_statement::build_struct(Function_type* fntype)
    2929              : {
    2930        13641 :   Location location = this->location();
    2931              : 
    2932        13641 :   Struct_field_list* fields = new Struct_field_list();
    2933              : 
    2934        13641 :   Call_expression* ce = this->call_->call_expression();
    2935        13641 :   Expression* fn = ce->fn();
    2936              : 
    2937        13641 :   if (!this->is_constant_function())
    2938              :     {
    2939              :       // The function to call.
    2940         7562 :       fields->push_back(Struct_field(Typed_identifier("fn", fntype,
    2941         3781 :                                                       location)));
    2942              :     }
    2943              : 
    2944              :   // If this thunk statement calls a method on an interface, we pass
    2945              :   // the interface object to the thunk.
    2946        13641 :   Interface_field_reference_expression* interface_method =
    2947        14555 :     fn->interface_field_reference_expression();
    2948          914 :   if (interface_method != NULL)
    2949              :     {
    2950          914 :       Typed_identifier tid("object", interface_method->expr()->type(),
    2951         1828 :                            location);
    2952          914 :       fields->push_back(Struct_field(tid));
    2953          914 :     }
    2954              : 
    2955              :   // If this thunk statement calls a bound method expression, as in
    2956              :   // "go s.m()", we pass the bound method argument to the thunk,
    2957              :   // to ensure that we make a copy of it if needed.
    2958        13641 :   Bound_method_expression* bme = fn->bound_method_expression();
    2959         5513 :   if (bme != NULL)
    2960              :     {
    2961        11026 :       Typed_identifier tid("object", bme->first_argument()->type(), location);
    2962         5513 :       fields->push_back(Struct_field(tid));
    2963         5513 :     }
    2964              : 
    2965        13641 :   const Expression_list* args = ce->args();
    2966        13641 :   if (args != NULL)
    2967              :     {
    2968         3620 :       int i = 0;
    2969         3620 :       for (Expression_list::const_iterator p = args->begin();
    2970         8610 :            p != args->end();
    2971         4990 :            ++p, ++i)
    2972              :         {
    2973         4990 :           if ((*p)->is_constant())
    2974          499 :             continue;
    2975              : 
    2976         4491 :           char buf[50];
    2977         4491 :           this->thunk_field_param(i, buf, sizeof buf);
    2978         8982 :           fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
    2979         8982 :                                                           location)));
    2980              :         }
    2981              :     }
    2982              : 
    2983        13641 :   Struct_type *st = Type::make_struct_type(fields, location);
    2984        13641 :   st->set_is_struct_incomparable();
    2985        13641 :   return st;
    2986              : }
    2987              : 
    2988              : // Build the thunk we are going to call.  This is a brand new, albeit
    2989              : // artificial, function.
    2990              : 
    2991              : void
    2992        13641 : Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
    2993              :                              Struct_type* struct_type)
    2994              : {
    2995        13641 :   Location location = this->location();
    2996              : 
    2997        13641 :   Call_expression* ce = this->call_->call_expression();
    2998              : 
    2999        13641 :   bool may_call_recover = false;
    3000        13641 :   if (this->classification() == STATEMENT_DEFER)
    3001              :     {
    3002        11230 :       Func_expression* fn = ce->fn()->func_expression();
    3003         4474 :       if (fn == NULL)
    3004              :         may_call_recover = true;
    3005              :       else
    3006              :         {
    3007         4474 :           const Named_object* no = fn->named_object();
    3008         4474 :           if (!no->is_function())
    3009              :             may_call_recover = true;
    3010              :           else
    3011         3391 :             may_call_recover = no->func_value()->calls_recover();
    3012              :         }
    3013              :     }
    3014              : 
    3015              :   // Build the type of the thunk.  The thunk takes a single parameter,
    3016              :   // which is a pointer to the special structure we build.
    3017        13641 :   const char* const parameter_name = "__go_thunk_parameter";
    3018        13641 :   Typed_identifier_list* thunk_parameters = new Typed_identifier_list();
    3019        13641 :   Type* pointer_to_struct_type = Type::make_pointer_type(struct_type);
    3020        27282 :   thunk_parameters->push_back(Typed_identifier(parameter_name,
    3021              :                                                pointer_to_struct_type,
    3022        13641 :                                                location));
    3023              : 
    3024        13641 :   Typed_identifier_list* thunk_results = NULL;
    3025        13641 :   if (may_call_recover)
    3026              :     {
    3027              :       // When deferring a function which may call recover, add a
    3028              :       // return value, to disable tail call optimizations which will
    3029              :       // break the way we check whether recover is permitted.
    3030         8840 :       thunk_results = new Typed_identifier_list();
    3031        17680 :       thunk_results->push_back(Typed_identifier("", Type::lookup_bool_type(),
    3032         8840 :                                                 location));
    3033              :     }
    3034              : 
    3035        13641 :   Function_type* thunk_type = Type::make_function_type(NULL, thunk_parameters,
    3036              :                                                        thunk_results,
    3037              :                                                        location);
    3038              : 
    3039              :   // Start building the thunk.
    3040        13641 :   Named_object* function = gogo->start_function(thunk_name, thunk_type, true,
    3041              :                                                 location);
    3042              : 
    3043        13641 :   gogo->start_block(location);
    3044              : 
    3045              :   // For a defer statement, start with a call to
    3046              :   // __go_set_defer_retaddr.  */
    3047        13641 :   Label* retaddr_label = NULL;
    3048        13641 :   if (may_call_recover)
    3049              :     {
    3050         8840 :       retaddr_label = gogo->add_label_reference("retaddr", location, false);
    3051         8840 :       Expression* arg = Expression::make_label_addr(retaddr_label, location);
    3052         8840 :       Expression* call = Runtime::make_call(gogo, Runtime::SETDEFERRETADDR,
    3053              :                                             location, 1, arg);
    3054              : 
    3055              :       // This is a hack to prevent the middle-end from deleting the
    3056              :       // label.
    3057         8840 :       gogo->start_block(location);
    3058         8840 :       gogo->add_statement(Statement::make_goto_statement(retaddr_label,
    3059              :                                                          location));
    3060         8840 :       Block* then_block = gogo->finish_block(location);
    3061         8840 :       then_block->determine_types(gogo);
    3062              : 
    3063         8840 :       Statement* s = Statement::make_if_statement(call, then_block, NULL,
    3064              :                                                   location);
    3065         8840 :       s->determine_types(gogo);
    3066         8840 :       gogo->add_statement(s);
    3067              : 
    3068         8840 :       function->func_value()->set_calls_defer_retaddr();
    3069              :     }
    3070              : 
    3071              :   // Get a reference to the parameter.
    3072        13641 :   Named_object* named_parameter = gogo->lookup(parameter_name, NULL);
    3073        13641 :   go_assert(named_parameter != NULL && named_parameter->is_variable());
    3074              : 
    3075              :   // Build the call.  Note that the field names are the same as the
    3076              :   // ones used in build_struct.
    3077        13641 :   Expression* thunk_parameter = Expression::make_var_reference(named_parameter,
    3078              :                                                                location);
    3079        13641 :   thunk_parameter =
    3080        13641 :       Expression::make_dereference(thunk_parameter,
    3081              :                                    Expression::NIL_CHECK_NOT_NEEDED,
    3082              :                                    location);
    3083              : 
    3084        13641 :   Interface_field_reference_expression* interface_method =
    3085        13641 :     ce->fn()->interface_field_reference_expression();
    3086        13641 :   Bound_method_expression* bme = ce->fn()->bound_method_expression();
    3087              : 
    3088        13641 :   Expression* func_to_call;
    3089        13641 :   unsigned int next_index;
    3090        13641 :   if (this->is_constant_function())
    3091              :     {
    3092         9860 :       func_to_call = ce->fn();
    3093         9860 :       next_index = 0;
    3094              :     }
    3095              :   else
    3096              :     {
    3097         3781 :       func_to_call = Expression::make_field_reference(thunk_parameter,
    3098              :                                                       0, location);
    3099         3781 :       next_index = 1;
    3100              :     }
    3101              : 
    3102        13641 :   if (interface_method != NULL)
    3103              :     {
    3104              :       // The main program passes the interface object.
    3105          914 :       go_assert(next_index == 0);
    3106          914 :       Expression* r = Expression::make_field_reference(thunk_parameter, 0,
    3107              :                                                        location);
    3108          914 :       const std::string& name(interface_method->name());
    3109          914 :       func_to_call = Expression::make_interface_field_reference(r, name,
    3110              :                                                                 location);
    3111          914 :       next_index = 1;
    3112              :     }
    3113              : 
    3114        13641 :   if (bme != NULL)
    3115              :     {
    3116              :       // This is a call to a method.
    3117         5513 :       go_assert(next_index == 0);
    3118         5513 :       Expression* r = Expression::make_field_reference(thunk_parameter, 0,
    3119              :                                                        location);
    3120         5513 :       func_to_call = Expression::make_bound_method(r, bme->method(),
    3121              :                                                    bme->function(), location);
    3122         5513 :       next_index = 1;
    3123              :     }
    3124              : 
    3125        13641 :   Expression_list* call_params = new Expression_list();
    3126        13641 :   const Struct_field_list* fields = struct_type->fields();
    3127        13641 :   Struct_field_list::const_iterator p = fields->begin();
    3128        13641 :   for (unsigned int i = 0; i < next_index; ++i)
    3129              :     ++p;
    3130        13641 :   bool is_recover_call = ce->is_recover_call();
    3131        13641 :   Expression* recover_arg = NULL;
    3132              : 
    3133        13641 :   const Expression_list* args = ce->args();
    3134        13641 :   if (args != NULL)
    3135              :     {
    3136         8610 :       for (Expression_list::const_iterator arg = args->begin();
    3137         8610 :            arg != args->end();
    3138         4990 :            ++arg)
    3139              :         {
    3140         4990 :           Expression* param;
    3141         4990 :           if ((*arg)->is_constant())
    3142          499 :             param = *arg;
    3143              :           else
    3144              :             {
    3145         4491 :               Expression* thunk_param =
    3146         4491 :                 Expression::make_var_reference(named_parameter, location);
    3147         4491 :              thunk_param =
    3148         4491 :                  Expression::make_dereference(thunk_param,
    3149              :                                               Expression::NIL_CHECK_NOT_NEEDED,
    3150              :                                               location);
    3151         4491 :               param = Expression::make_field_reference(thunk_param,
    3152              :                                                        next_index,
    3153              :                                                        location);
    3154         4491 :               ++next_index;
    3155              :             }
    3156              : 
    3157         4990 :           if (!is_recover_call)
    3158         4980 :             call_params->push_back(param);
    3159              :           else
    3160              :             {
    3161           10 :               go_assert(call_params->empty());
    3162              :               recover_arg = param;
    3163              :             }
    3164              :         }
    3165              :     }
    3166              : 
    3167        13641 :   if (call_params->empty())
    3168              :     {
    3169        10031 :       delete call_params;
    3170        10031 :       call_params = NULL;
    3171              :     }
    3172              : 
    3173        13641 :   Call_expression* call = Expression::make_call(func_to_call, call_params,
    3174              :                                                 false, location);
    3175              : 
    3176              :   // This call expression was already lowered before entering the
    3177              :   // thunk statement.  Don't try to lower varargs again, as that will
    3178              :   // cause confusion for, e.g., method calls which already have a
    3179              :   // receiver parameter.
    3180        13641 :   call->set_varargs_are_lowered();
    3181              : 
    3182        13641 :   Statement* call_statement = Statement::make_statement(call, true);
    3183              : 
    3184        13641 :   call_statement->determine_types(gogo);
    3185        13641 :   gogo->add_statement(call_statement);
    3186              : 
    3187              :   // If this is a defer statement, the label comes immediately after
    3188              :   // the call.
    3189        13641 :   if (may_call_recover)
    3190              :     {
    3191         8840 :       gogo->add_label_definition("retaddr", location);
    3192              : 
    3193         8840 :       Expression_list* vals = new Expression_list();
    3194         8840 :       vals->push_back(Expression::make_boolean(false, location));
    3195         8840 :       Statement* s = Statement::make_return_statement(function, vals,
    3196              :                                                       location);
    3197         8840 :       s->determine_types(gogo);
    3198         8840 :       gogo->add_statement(s);
    3199              :     }
    3200              : 
    3201        13641 :   Block* b = gogo->finish_block(location);
    3202              : 
    3203        13641 :   gogo->add_block(b, location);
    3204              : 
    3205        13641 :   gogo->lower_block(function, b);
    3206              : 
    3207              :   // We already ran the determine_types pass, so we need to run it
    3208              :   // just for the call statement now.  The other types are known.
    3209        13641 :   call_statement->determine_types(gogo);
    3210              : 
    3211        13641 :   gogo->add_conversions_in_block(b);
    3212              : 
    3213        13641 :   if (may_call_recover
    3214        13641 :       || recover_arg != NULL
    3215        13641 :       || this->classification() == STATEMENT_GO)
    3216              :     {
    3217              :       // Dig up the call expression, which may have been changed
    3218              :       // during lowering.
    3219        11251 :       go_assert(call_statement->classification() == STATEMENT_EXPRESSION);
    3220        11251 :       Expression_statement* es =
    3221              :         static_cast<Expression_statement*>(call_statement);
    3222        11251 :       ce = es->expr()->call_expression();
    3223        11251 :       if (ce == NULL)
    3224            0 :         go_assert(saw_errors());
    3225              :       else
    3226              :         {
    3227        11251 :           if (may_call_recover)
    3228         8840 :             ce->set_is_deferred();
    3229        11251 :           if (this->classification() == STATEMENT_GO)
    3230         2411 :             ce->set_is_concurrent();
    3231        11251 :           if (recover_arg != NULL)
    3232           10 :             ce->set_recover_arg(recover_arg);
    3233              :         }
    3234              :     }
    3235              : 
    3236        13641 :   gogo->flatten_block(function, b);
    3237              : 
    3238              :   // That is all the thunk has to do.
    3239        13641 :   gogo->finish_function(location);
    3240        13641 : }
    3241              : 
    3242              : // Get the function and argument expressions.
    3243              : 
    3244              : bool
    3245        13741 : Thunk_statement::get_fn_and_arg(Expression** pfn, Expression** parg)
    3246              : {
    3247        13741 :   if (this->call_->is_error_expression())
    3248              :     return false;
    3249              : 
    3250        13741 :   Call_expression* ce = this->call_->call_expression();
    3251              : 
    3252        13741 :   Expression* fn = ce->fn();
    3253        13741 :   Func_expression* fe = fn->func_expression();
    3254            0 :   go_assert(fe != NULL);
    3255        13741 :   *pfn = Expression::make_func_code_reference(fe->named_object(),
    3256              :                                               fe->location());
    3257              : 
    3258        13741 :   const Expression_list* args = ce->args();
    3259        13741 :   if (args == NULL || args->empty())
    3260           81 :     *parg = Expression::make_nil(this->location());
    3261              :   else
    3262              :     {
    3263        13660 :       go_assert(args->size() == 1);
    3264        13660 :       *parg = args->front();
    3265              :     }
    3266              : 
    3267              :   return true;
    3268              : }
    3269              : 
    3270              : // Class Go_statement.
    3271              : 
    3272              : Bstatement*
    3273         2512 : Go_statement::do_get_backend(Translate_context* context)
    3274              : {
    3275         2512 :   Expression* fn;
    3276         2512 :   Expression* arg;
    3277         2512 :   if (!this->get_fn_and_arg(&fn, &arg))
    3278            0 :     return context->backend()->error_statement();
    3279              : 
    3280         2512 :   Gogo* gogo = context->gogo();
    3281         2512 :   Expression* call = Runtime::make_call(gogo, Runtime::GO, this->location(), 2,
    3282              :                                         fn, arg);
    3283         2512 :   call->determine_type_no_context(gogo);
    3284         2512 :   Bexpression* bcall = call->get_backend(context);
    3285         2512 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    3286         2512 :   return context->backend()->expression_statement(bfunction, bcall);
    3287              : }
    3288              : 
    3289              : // Dump the AST representation for go statement.
    3290              : 
    3291              : void
    3292            0 : Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3293              : {
    3294            0 :   ast_dump_context->print_indent();
    3295            0 :   ast_dump_context->ostream() << "go ";
    3296            0 :   ast_dump_context->dump_expression(this->call());
    3297            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3298            0 : }
    3299              : 
    3300              : // Make a go statement.
    3301              : 
    3302              : Statement*
    3303         4941 : Statement::make_go_statement(Call_expression* call, Location location)
    3304              : {
    3305         4941 :   return new Go_statement(call, location);
    3306              : }
    3307              : 
    3308              : // Class Defer_statement.
    3309              : 
    3310              : Bstatement*
    3311        11229 : Defer_statement::do_get_backend(Translate_context* context)
    3312              : {
    3313        11229 :   Expression* fn;
    3314        11229 :   Expression* arg;
    3315        11229 :   if (!this->get_fn_and_arg(&fn, &arg))
    3316            0 :     return context->backend()->error_statement();
    3317              : 
    3318        11229 :   Gogo* gogo = context->gogo();
    3319        11229 :   Location loc = this->location();
    3320        11229 :   Expression* ds = context->function()->func_value()->defer_stack(loc);
    3321              : 
    3322        11229 :   Expression* call;
    3323        11229 :   if (this->on_stack_)
    3324              :     {
    3325        10957 :       if (gogo->debug_optimization())
    3326            0 :         go_debug(loc, "stack allocated defer");
    3327              : 
    3328        10957 :       Type* defer_type = Defer_statement::defer_struct_type();
    3329        10957 :       Expression* defer = Expression::make_allocation(defer_type, loc);
    3330        10957 :       defer->allocation_expression()->set_allocate_on_stack();
    3331        10957 :       defer->allocation_expression()->set_no_zero();
    3332        10957 :       call = Runtime::make_call(gogo, Runtime::DEFERPROCSTACK, loc, 4,
    3333              :                                 defer, ds, fn, arg);
    3334              :     }
    3335              :   else
    3336          272 :     call = Runtime::make_call(gogo, Runtime::DEFERPROC, loc, 3,
    3337              :                               ds, fn, arg);
    3338        11229 :   call->determine_type_no_context(gogo);
    3339        11229 :   Bexpression* bcall = call->get_backend(context);
    3340        11229 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    3341        11229 :   return context->backend()->expression_statement(bfunction, bcall);
    3342              : }
    3343              : 
    3344              : Type*
    3345        10957 : Defer_statement::defer_struct_type()
    3346              : {
    3347        10957 :   Type* ptr_type = Type::make_pointer_type(Type::make_void_type());
    3348        10957 :   Type* uintptr_type = Type::lookup_integer_type("uintptr");
    3349        10957 :   Type* bool_type = Type::make_boolean_type();
    3350        10957 :   return Type::make_builtin_struct_type(9,
    3351              :                                         "link", ptr_type,
    3352              :                                         "frame", ptr_type,
    3353              :                                         "panicStack", ptr_type,
    3354              :                                         "_panic", ptr_type,
    3355              :                                         "pfn", uintptr_type,
    3356              :                                         "arg", ptr_type,
    3357              :                                         "retaddr", uintptr_type,
    3358              :                                         "makefunccanrecover", bool_type,
    3359        10957 :                                         "heap", bool_type);
    3360              : }
    3361              : 
    3362              : // Dump the AST representation for defer statement.
    3363              : 
    3364              : void
    3365            0 : Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3366              : {
    3367            0 :   ast_dump_context->print_indent();
    3368            0 :   ast_dump_context->ostream() << "defer ";
    3369            0 :   ast_dump_context->dump_expression(this->call());
    3370            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3371            0 : }
    3372              : 
    3373              : // Make a defer statement.
    3374              : 
    3375              : Statement*
    3376        22582 : Statement::make_defer_statement(Call_expression* call,
    3377              :                                 Location location)
    3378              : {
    3379        22582 :   return new Defer_statement(call, location);
    3380              : }
    3381              : 
    3382              : // Class Return_statement.
    3383              : 
    3384              : void
    3385       603760 : Return_statement::do_determine_types(Gogo* gogo)
    3386              : {
    3387       603760 :   if (this->types_are_determined_)
    3388              :     return;
    3389       373042 :   this->types_are_determined_ = true;
    3390              : 
    3391       373042 :   size_t vals_count = this->vals_ == NULL ? 0 : this->vals_->size();
    3392       341510 :   if (vals_count == 0)
    3393              :     return;
    3394              : 
    3395       341510 :   Function::Results* results =
    3396       341510 :     this->function_->func_value()->result_variables();
    3397       683016 :   size_t results_count = results == NULL ? 0 : results->size();
    3398              : 
    3399              :   // If the current function has multiple return values, and we are
    3400              :   // returning a single call expression, split up the call expression.
    3401       341510 :   if (results_count > 1
    3402       341510 :       && vals_count == 1
    3403       341510 :       && this->vals_->front()->call_expression() != NULL)
    3404              :     {
    3405         4963 :       Call_expression* call = this->vals_->front()->call_expression();
    3406         4963 :       call->set_expected_result_count(results_count);
    3407         4963 :       call->determine_type_no_context(gogo);
    3408         9926 :       delete this->vals_;
    3409         4963 :       this->vals_ = new Expression_list();
    3410        15266 :       for (size_t i = 0; i < results_count; ++i)
    3411        10303 :         this->vals_->push_back(Expression::make_call_result(call, i));
    3412              :       vals_count = results_count;
    3413              :     }
    3414              : 
    3415       341510 :   if (vals_count != results_count)
    3416              :     {
    3417              :       // This is an error which we will report later.  Determine all
    3418              :       // types to avoid knockon errors.
    3419           42 :       for (Expression_list::const_iterator pe = this->vals_->begin();
    3420           42 :            pe != this->vals_->end();
    3421           27 :            ++pe)
    3422           27 :         (*pe)->determine_type_no_context(gogo);
    3423              :       return;
    3424              :     }
    3425              : 
    3426       341495 :   Expression_list::const_iterator pe = this->vals_->begin();
    3427       341495 :   for (Function::Results::const_iterator pr = results->begin();
    3428       746373 :        pr != results->end();
    3429       404878 :        ++pr, ++pe)
    3430              :     {
    3431       404878 :       Type* rvtype = (*pr)->result_var_value()->type();
    3432       404878 :       Type_context context(rvtype, false);
    3433       404878 :       (*pe)->determine_type(gogo, &context);
    3434              :     }
    3435              : }
    3436              : 
    3437              : void
    3438       210139 : Return_statement::do_check_types(Gogo*)
    3439              : {
    3440       210139 :   size_t vals_count = this->vals_ == NULL ? 0 : this->vals_->size();
    3441       210139 :   Function::Results* results =
    3442       210139 :     this->function_->func_value()->result_variables();
    3443       409225 :   size_t results_count = results == NULL ? 0 : results->size();
    3444              : 
    3445       210139 :   if (vals_count == 0)
    3446              :     {
    3447        18953 :       if (results_count > 0
    3448        18953 :           && !this->function_->func_value()->results_are_named())
    3449            1 :         this->report_error(_("not enough arguments to return"));
    3450        18953 :       return;
    3451              :     }
    3452              : 
    3453       191186 :   if (results_count == 0)
    3454              :     {
    3455            4 :       this->report_error(_("return with value in function "
    3456              :                            "with no return type"));
    3457            8 :       delete this->vals_;
    3458            4 :       this->vals_ = NULL;
    3459            4 :       return;
    3460              :     }
    3461              : 
    3462       191182 :   if (vals_count < results_count)
    3463              :     {
    3464            8 :       this->report_error(_("not enough arguments to return"));
    3465            8 :       return;
    3466              :     }
    3467              : 
    3468       191174 :   if (vals_count > results_count)
    3469              :     {
    3470            3 :       this->report_error(_("too many values in return statement"));
    3471            3 :       return;
    3472              :     }
    3473              : 
    3474       191171 :   Expression_list::const_iterator pe = this->vals_->begin();
    3475       191171 :   int i = 1;
    3476       191171 :   for (Function::Results::const_iterator pr = results->begin();
    3477       445653 :        pr != results->end();
    3478       254482 :        ++pr, ++pe, ++i)
    3479              :     {
    3480       254482 :       Named_object* rv = *pr;
    3481       254482 :       Expression* e = *pe;
    3482              : 
    3483       254482 :       std::string reason;
    3484       254482 :       if (!Type::are_assignable(rv->result_var_value()->type(), e->type(),
    3485              :                                 &reason))
    3486              :         {
    3487            7 :           if (reason.empty())
    3488            0 :             go_error_at(e->location(),
    3489              :                         "incompatible type for return value %d", i);
    3490              :           else
    3491            7 :             go_error_at(e->location(),
    3492              :                         "incompatible type for return value %d (%s)",
    3493              :                         i, reason.c_str());
    3494            7 :           this->set_is_error();
    3495              :         }
    3496       254482 :     }
    3497              : }
    3498              : 
    3499              : // Lower a return statement.  If we are returning a function call
    3500              : // which returns multiple values which match the current function,
    3501              : // split up the call's results.  If the return statement lists
    3502              : // explicit values, implement this statement by assigning the values
    3503              : // to the result variables and change this statement to a naked
    3504              : // return.  This lets panic/recover work correctly.
    3505              : 
    3506              : Statement*
    3507       789618 : Return_statement::do_lower(Gogo* gogo, Named_object*,
    3508              :                            Block* enclosing, Statement_inserter*)
    3509              : {
    3510       789618 :   Location loc = this->location();
    3511              : 
    3512       789618 :   if (this->classification() == STATEMENT_ERROR)
    3513            0 :     return Statement::make_error_statement(loc);
    3514              : 
    3515       789618 :   if (this->is_lowered_)
    3516       416600 :     return this;
    3517              : 
    3518       373018 :   Expression_list* vals = this->vals_;
    3519       373018 :   this->vals_ = NULL;
    3520       373018 :   this->is_lowered_ = true;
    3521              : 
    3522       373018 :   size_t vals_count = vals == NULL ? 0 : vals->size();
    3523              : 
    3524       341487 :   if (vals_count == 0)
    3525        31531 :     return this;
    3526              : 
    3527       341487 :   Function::Results* results =
    3528       341487 :     this->function_->func_value()->result_variables();
    3529       682974 :   size_t results_count = results == NULL ? 0 : results->size();
    3530              : 
    3531       341487 :   go_assert(vals_count == results_count);
    3532              : 
    3533       341487 :   Block* b = new Block(enclosing, loc);
    3534              : 
    3535       341487 :   Expression_list* lhs = new Expression_list();
    3536       341487 :   Expression_list* rhs = new Expression_list();
    3537              : 
    3538       341487 :   Expression_list::const_iterator pe = vals->begin();
    3539       341487 :   for (Function::Results::const_iterator pr = results->begin();
    3540       746355 :        pr != results->end();
    3541       404868 :        ++pr, ++pe)
    3542              :     {
    3543       404868 :       Named_object* rv = *pr;
    3544       404868 :       Expression* e = *pe;
    3545       404868 :       Expression* ve = Expression::make_var_reference(rv, e->location());
    3546       404868 :       lhs->push_back(ve);
    3547       404868 :       rhs->push_back(e);
    3548              :     }
    3549              : 
    3550       341487 :   if (lhs->size() == 1)
    3551              :     {
    3552       287473 :       Statement* s = Statement::make_assignment(lhs->front(), rhs->front(),
    3553              :                                                 loc);
    3554       287473 :       s->determine_types(gogo);
    3555       287473 :       b->add_statement(s);
    3556       287473 :       delete lhs;
    3557       287473 :       delete rhs;
    3558              :     }
    3559              :   else
    3560              :     {
    3561        54014 :       Statement* s = Statement::make_tuple_assignment(lhs, rhs, loc);
    3562        54014 :       s->determine_types(gogo);
    3563        54014 :       b->add_statement(s);
    3564              :     }
    3565              : 
    3566       341487 :   b->add_statement(this);
    3567              : 
    3568       341487 :   delete vals;
    3569              : 
    3570       341487 :   return Statement::make_block_statement(b, loc);
    3571              : }
    3572              : 
    3573              : // Convert a return statement to the backend representation.
    3574              : 
    3575              : Bstatement*
    3576       372486 : Return_statement::do_get_backend(Translate_context* context)
    3577              : {
    3578       372486 :   Location loc = this->location();
    3579              : 
    3580       372486 :   Function* function = context->function()->func_value();
    3581       372486 :   Function::Results* results = function->result_variables();
    3582       372486 :   std::vector<Bexpression*> retvals;
    3583       372486 :   if (results != NULL && !results->empty())
    3584              :     {
    3585       361543 :       retvals.reserve(results->size());
    3586       361543 :       for (Function::Results::const_iterator p = results->begin();
    3587       795675 :            p != results->end();
    3588       434132 :            p++)
    3589              :         {
    3590       434132 :           Expression* vr = Expression::make_var_reference(*p, loc);
    3591       434132 :           retvals.push_back(vr->get_backend(context));
    3592              :         }
    3593              :     }
    3594              : 
    3595       372486 :   return context->backend()->return_statement(function->get_decl(),
    3596       372486 :                                               retvals, loc);
    3597       372486 : }
    3598              : 
    3599              : // Export a return statement.  At this point all the expressions have
    3600              : // been converted to assignments to the result variables, so this is
    3601              : // simple.
    3602              : 
    3603              : void
    3604        14161 : Return_statement::do_export_statement(Export_function_body* efb)
    3605              : {
    3606        14161 :   efb->write_c_string("return");
    3607        14161 : }
    3608              : 
    3609              : // Dump the AST representation for a return statement.
    3610              : 
    3611              : void
    3612            0 : Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3613              : {
    3614            0 :   ast_dump_context->print_indent();
    3615            0 :   ast_dump_context->ostream() << "return " ;
    3616            0 :   ast_dump_context->dump_expression_list(this->vals_);
    3617            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3618            0 : }
    3619              : 
    3620              : // Make a return statement.
    3621              : 
    3622              : Return_statement*
    3623       373042 : Statement::make_return_statement(Named_object* function, Expression_list* vals,
    3624              :                                  Location location)
    3625              : {
    3626       373042 :   return new Return_statement(function, vals, location);
    3627              : }
    3628              : 
    3629              : // Make a statement that returns the result of a call expression.
    3630              : 
    3631              : Statement*
    3632         2137 : Statement::make_return_from_call(Named_object* function, Call_expression* call,
    3633              :                                  Location location)
    3634              : {
    3635         2137 :   size_t rc = call->result_count();
    3636         2137 :   if (rc == 0)
    3637         1349 :     return Statement::make_statement(call, true);
    3638              :   else
    3639              :     {
    3640          788 :       Expression_list* vals = new Expression_list();
    3641          788 :       if (rc == 1)
    3642          672 :         vals->push_back(call);
    3643              :       else
    3644              :         {
    3645          354 :           for (size_t i = 0; i < rc; ++i)
    3646          238 :             vals->push_back(Expression::make_call_result(call, i));
    3647              :         }
    3648          788 :       return Statement::make_return_statement(function, vals, location);
    3649              :     }
    3650              : }
    3651              : 
    3652              : // A break or continue statement.
    3653              : 
    3654              : class Bc_statement : public Statement
    3655              : {
    3656              :  public:
    3657        18944 :   Bc_statement(bool is_break, Unnamed_label* label, Location location)
    3658        18944 :     : Statement(STATEMENT_BREAK_OR_CONTINUE, location),
    3659        37888 :       label_(label), is_break_(is_break)
    3660              :   { }
    3661              : 
    3662              :   bool
    3663              :   is_break() const
    3664              :   { return this->is_break_; }
    3665              : 
    3666              :  protected:
    3667              :   int
    3668       475942 :   do_traverse(Traverse*)
    3669       475942 :   { return TRAVERSE_CONTINUE; }
    3670              : 
    3671              :   bool
    3672            0 :   do_may_fall_through() const
    3673            0 :   { return false; }
    3674              : 
    3675              :   Bstatement*
    3676        18830 :   do_get_backend(Translate_context* context)
    3677        18830 :   { return this->label_->get_goto(context, this->location()); }
    3678              : 
    3679              :   void
    3680              :   do_dump_statement(Ast_dump_context*) const;
    3681              : 
    3682              :  private:
    3683              :   // The label that this branches to.
    3684              :   Unnamed_label* label_;
    3685              :   // True if this is "break", false if it is "continue".
    3686              :   bool is_break_;
    3687              : };
    3688              : 
    3689              : // Dump the AST representation for a break/continue statement
    3690              : 
    3691              : void
    3692            0 : Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3693              : {
    3694            0 :   ast_dump_context->print_indent();
    3695            0 :   ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
    3696            0 :   if (this->label_ != NULL)
    3697              :     {
    3698            0 :       ast_dump_context->ostream() << " ";
    3699            0 :       ast_dump_context->dump_label_name(this->label_);
    3700              :     }
    3701            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3702            0 : }
    3703              : 
    3704              : // Make a break statement.
    3705              : 
    3706              : Statement*
    3707         8149 : Statement::make_break_statement(Unnamed_label* label, Location location)
    3708              : {
    3709         8149 :   return new Bc_statement(true, label, location);
    3710              : }
    3711              : 
    3712              : // Make a continue statement.
    3713              : 
    3714              : Statement*
    3715        10795 : Statement::make_continue_statement(Unnamed_label* label,
    3716              :                                    Location location)
    3717              : {
    3718        10795 :   return new Bc_statement(false, label, location);
    3719              : }
    3720              : 
    3721              : // Class Goto_statement.
    3722              : 
    3723              : int
    3724       130014 : Goto_statement::do_traverse(Traverse*)
    3725              : {
    3726       130014 :   return TRAVERSE_CONTINUE;
    3727              : }
    3728              : 
    3729              : // Check types for a label.  There aren't any types per se, but we use
    3730              : // this to give an error if the label was never defined.
    3731              : 
    3732              : void
    3733         2101 : Goto_statement::do_check_types(Gogo*)
    3734              : {
    3735         2101 :   if (!this->label_->is_defined())
    3736              :     {
    3737            3 :       go_error_at(this->location(), "reference to undefined label %qs",
    3738            3 :                   Gogo::message_name(this->label_->name()).c_str());
    3739            3 :       this->set_is_error();
    3740              :     }
    3741         2101 : }
    3742              : 
    3743              : // Convert the goto statement to the backend representation.
    3744              : 
    3745              : Bstatement*
    3746        10842 : Goto_statement::do_get_backend(Translate_context* context)
    3747              : {
    3748        10842 :   Blabel* blabel = this->label_->get_backend_label(context);
    3749        10842 :   return context->backend()->goto_statement(blabel, this->location());
    3750              : }
    3751              : 
    3752              : // Export a goto statement.
    3753              : 
    3754              : void
    3755            8 : Goto_statement::do_export_statement(Export_function_body *efb)
    3756              : {
    3757            8 :   efb->write_c_string("goto ");
    3758            8 :   efb->write_string(this->label_->name());
    3759            8 : }
    3760              : 
    3761              : // Import a goto or goto unnamed statement.
    3762              : 
    3763              : Statement*
    3764         1523 : Goto_statement::do_import(Import_function_body* ifb, Location loc)
    3765              : {
    3766         1523 :   ifb->require_c_string("goto ");
    3767         1523 :   std::string id = ifb->read_identifier();
    3768         1523 :   if (id[0] != '$')
    3769              :     {
    3770            1 :       Function* fn = ifb->function()->func_value();
    3771            1 :       Label* label = fn->add_label_reference(ifb->gogo(), id, loc, false);
    3772            1 :       return Statement::make_goto_statement(label, loc);
    3773              :     }
    3774              :   else
    3775              :     {
    3776         1522 :       if (id[1] != 'l')
    3777              :         {
    3778            0 :           if (!ifb->saw_error())
    3779            0 :             go_error_at(loc,
    3780              :                         ("invalid export data for %qs: "
    3781              :                          "bad unnamed label at %lu"),
    3782            0 :                         ifb->name().c_str(),
    3783            0 :                         static_cast<unsigned long>(ifb->off()));
    3784            0 :           ifb->set_saw_error();
    3785            0 :           return Statement::make_error_statement(loc);
    3786              :         }
    3787         1522 :       const char* p = id.c_str();
    3788         1522 :       char* end;
    3789         1522 :       long idx = strtol(p + 2, &end, 10);
    3790         1522 :       if (*end != '\0' || idx > 0x7fffffff)
    3791              :         {
    3792            0 :           if (!ifb->saw_error())
    3793            0 :             go_error_at(loc,
    3794              :                         ("invalid export data for %qs: "
    3795              :                          "bad unnamed label index at %lu"),
    3796            0 :                         ifb->name().c_str(),
    3797            0 :                         static_cast<unsigned long>(ifb->off()));
    3798            0 :           ifb->set_saw_error();
    3799            0 :           return Statement::make_error_statement(loc);
    3800              :         }
    3801              : 
    3802         1522 :       Unnamed_label* label = ifb->unnamed_label(idx, loc);
    3803         1522 :       return Statement::make_goto_unnamed_statement(label, loc);
    3804              :     }
    3805         1523 : }
    3806              : 
    3807              : // Dump the AST representation for a goto statement.
    3808              : 
    3809              : void
    3810            0 : Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3811              : {
    3812            0 :   ast_dump_context->print_indent();
    3813            0 :   ast_dump_context->ostream() << "goto " << this->label_->name() << dsuffix(location()) << std::endl;
    3814            0 : }
    3815              : 
    3816              : // Make a goto statement.
    3817              : 
    3818              : Statement*
    3819        10942 : Statement::make_goto_statement(Label* label, Location location)
    3820              : {
    3821        10942 :   return new Goto_statement(label, location);
    3822              : }
    3823              : 
    3824              : // Class Goto_unnamed_statement.
    3825              : 
    3826              : int
    3827      3378213 : Goto_unnamed_statement::do_traverse(Traverse*)
    3828              : {
    3829      3378213 :   return TRAVERSE_CONTINUE;
    3830              : }
    3831              : 
    3832              : // Convert the goto unnamed statement to the backend representation.
    3833              : 
    3834              : Bstatement*
    3835       175104 : Goto_unnamed_statement::do_get_backend(Translate_context* context)
    3836              : {
    3837       175104 :   return this->label_->get_goto(context, this->location());
    3838              : }
    3839              : 
    3840              : // Export a goto unnamed statement.
    3841              : 
    3842              : void
    3843         1703 : Goto_unnamed_statement::do_export_statement(Export_function_body *efb)
    3844              : {
    3845         1703 :   unsigned int index = efb->unnamed_label_index(this->label_);
    3846         1703 :   char buf[100];
    3847         1703 :   snprintf(buf, sizeof buf, "goto $l%u", index);
    3848         1703 :   efb->write_c_string(buf);
    3849         1703 : }
    3850              : 
    3851              : // Dump the AST representation for an unnamed goto statement
    3852              : 
    3853              : void
    3854            0 : Goto_unnamed_statement::do_dump_statement(
    3855              :     Ast_dump_context* ast_dump_context) const
    3856              : {
    3857            0 :   ast_dump_context->print_indent();
    3858            0 :   ast_dump_context->ostream() << "goto ";
    3859            0 :   ast_dump_context->dump_label_name(this->label_);
    3860            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    3861            0 : }
    3862              : 
    3863              : // Make a goto statement to an unnamed label.
    3864              : 
    3865              : Statement*
    3866       175691 : Statement::make_goto_unnamed_statement(Unnamed_label* label,
    3867              :                                        Location location)
    3868              : {
    3869       175691 :   return new Goto_unnamed_statement(label, location);
    3870              : }
    3871              : 
    3872              : // Class Label_statement.
    3873              : 
    3874              : // Traversal.
    3875              : 
    3876              : int
    3877       120608 : Label_statement::do_traverse(Traverse*)
    3878              : {
    3879       120608 :   return TRAVERSE_CONTINUE;
    3880              : }
    3881              : 
    3882              : // Return the backend representation of the statement defining this
    3883              : // label.
    3884              : 
    3885              : Bstatement*
    3886        10415 : Label_statement::do_get_backend(Translate_context* context)
    3887              : {
    3888        10415 :   if (this->label_->is_dummy_label())
    3889              :     {
    3890            3 :       Bexpression* bce = context->backend()->boolean_constant_expression(false);
    3891            3 :       Bfunction* bfunction = context->function()->func_value()->get_decl();
    3892            3 :       return context->backend()->expression_statement(bfunction, bce);
    3893              :     }
    3894        10412 :   Blabel* blabel = this->label_->get_backend_label(context);
    3895        10412 :   return context->backend()->label_definition_statement(blabel);
    3896              : }
    3897              : 
    3898              : // Export a label.
    3899              : 
    3900              : void
    3901            8 : Label_statement::do_export_statement(Export_function_body* efb)
    3902              : {
    3903            8 :   if (this->label_->is_dummy_label())
    3904              :     return;
    3905              :   // We use a leading colon, not a trailing one, to simplify import.
    3906            8 :   efb->write_c_string(":");
    3907            8 :   efb->write_string(this->label_->name());
    3908              : }
    3909              : 
    3910              : // Import a label or an unnamed label.
    3911              : 
    3912              : Statement*
    3913         1434 : Label_statement::do_import(Import_function_body* ifb, Location loc)
    3914              : {
    3915         1434 :   ifb->require_c_string(":");
    3916         1434 :   std::string id = ifb->read_identifier();
    3917         1434 :   if (id[0] != '$')
    3918              :     {
    3919            1 :       Function* fn = ifb->function()->func_value();
    3920            1 :       Label* label = fn->add_label_definition(ifb->gogo(), id, loc);
    3921            1 :       return Statement::make_label_statement(label, loc);
    3922              :     }
    3923              :   else
    3924              :     {
    3925         1433 :       if (id[1] != 'l')
    3926              :         {
    3927            0 :           if (!ifb->saw_error())
    3928            0 :             go_error_at(loc,
    3929              :                         ("invalid export data for %qs: "
    3930              :                          "bad unnamed label at %lu"),
    3931            0 :                         ifb->name().c_str(),
    3932            0 :                         static_cast<unsigned long>(ifb->off()));
    3933            0 :           ifb->set_saw_error();
    3934            0 :           return Statement::make_error_statement(loc);
    3935              :         }
    3936         1433 :       const char* p = id.c_str();
    3937         1433 :       char* end;
    3938         1433 :       long idx = strtol(p + 2, &end, 10);
    3939         1433 :       if (*end != '\0' || idx > 0x7fffffff)
    3940              :         {
    3941            0 :           if (!ifb->saw_error())
    3942            0 :             go_error_at(loc,
    3943              :                         ("invalid export data for %qs: "
    3944              :                          "bad unnamed label index at %lu"),
    3945            0 :                         ifb->name().c_str(),
    3946            0 :                         static_cast<unsigned long>(ifb->off()));
    3947            0 :           ifb->set_saw_error();
    3948            0 :           return Statement::make_error_statement(loc);
    3949              :         }
    3950              : 
    3951         1433 :       Unnamed_label* label = ifb->unnamed_label(idx, loc);
    3952         1433 :       return Statement::make_unnamed_label_statement(label);
    3953              :     }
    3954         1434 : }
    3955              : 
    3956              : // Dump the AST for a label definition statement.
    3957              : 
    3958              : void
    3959            0 : Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    3960              : {
    3961            0 :   ast_dump_context->print_indent();
    3962            0 :   ast_dump_context->ostream() << this->label_->name() << ":" << dsuffix(location()) << std::endl;
    3963            0 : }
    3964              : 
    3965              : // Make a label statement.
    3966              : 
    3967              : Statement*
    3968        10526 : Statement::make_label_statement(Label* label, Location location)
    3969              : {
    3970        10526 :   return new Label_statement(label, location);
    3971              : }
    3972              : 
    3973              : // Class Unnamed_label_statement.
    3974              : 
    3975       167230 : Unnamed_label_statement::Unnamed_label_statement(Unnamed_label* label)
    3976              :   : Statement(STATEMENT_UNNAMED_LABEL, label->location()),
    3977       167230 :     label_(label)
    3978       167230 : { }
    3979              : 
    3980              : int
    3981      3185853 : Unnamed_label_statement::do_traverse(Traverse*)
    3982              : {
    3983      3185853 :   return TRAVERSE_CONTINUE;
    3984              : }
    3985              : 
    3986              : // Get the backend definition for this unnamed label statement.
    3987              : 
    3988              : Bstatement*
    3989       166614 : Unnamed_label_statement::do_get_backend(Translate_context* context)
    3990              : {
    3991       166614 :   return this->label_->get_definition(context);
    3992              : }
    3993              : 
    3994              : // Export an unnamed label.
    3995              : 
    3996              : void
    3997         1641 : Unnamed_label_statement::do_export_statement(Export_function_body* efb)
    3998              : {
    3999         1641 :   unsigned int index = efb->unnamed_label_index(this->label_);
    4000         1641 :   char buf[50];
    4001              :   // We use a leading colon, not a trailing one, to simplify import.
    4002         1641 :   snprintf(buf, sizeof buf, ":$l%u", index);
    4003         1641 :   efb->write_c_string(buf);
    4004         1641 : }
    4005              : 
    4006              : // Dump the AST representation for an unnamed label definition statement.
    4007              : 
    4008              : void
    4009            0 : Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    4010              :     const
    4011              : {
    4012            0 :   ast_dump_context->print_indent();
    4013            0 :   ast_dump_context->dump_label_name(this->label_);
    4014            0 :   ast_dump_context->ostream() << ":" << dsuffix(location()) << std::endl;
    4015            0 : }
    4016              : 
    4017              : // Make an unnamed label statement.
    4018              : 
    4019              : Statement*
    4020       167230 : Statement::make_unnamed_label_statement(Unnamed_label* label)
    4021              : {
    4022       167230 :   return new Unnamed_label_statement(label);
    4023              : }
    4024              : 
    4025              : // Class If_statement.
    4026              : 
    4027              : // Traversal.
    4028              : 
    4029              : int
    4030      9826893 : If_statement::do_traverse(Traverse* traverse)
    4031              : {
    4032      9826893 :   if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT
    4033      9826893 :       || this->then_block_->traverse(traverse) == TRAVERSE_EXIT)
    4034       359153 :     return TRAVERSE_EXIT;
    4035      9467740 :   if (this->else_block_ != NULL)
    4036              :     {
    4037       664448 :       if (this->else_block_->traverse(traverse) == TRAVERSE_EXIT)
    4038              :         return TRAVERSE_EXIT;
    4039              :     }
    4040              :   return TRAVERSE_CONTINUE;
    4041              : }
    4042              : 
    4043              : void
    4044       814416 : If_statement::do_determine_types(Gogo* gogo)
    4045              : {
    4046       814416 :   Type_context context(Type::lookup_bool_type(), false);
    4047       814416 :   this->cond_->determine_type(gogo, &context);
    4048       814416 :   this->then_block_->determine_types(gogo);
    4049       814416 :   if (this->else_block_ != NULL)
    4050       240906 :     this->else_block_->determine_types(gogo);
    4051       814416 : }
    4052              : 
    4053              : // Check types.
    4054              : 
    4055              : void
    4056       254022 : If_statement::do_check_types(Gogo*)
    4057              : {
    4058       254022 :   Type* type = this->cond_->type();
    4059       254022 :   if (type->is_error())
    4060           12 :     this->set_is_error();
    4061       254010 :   else if (!type->is_boolean_type())
    4062            3 :     this->report_error(_("expected boolean expression"));
    4063       254022 : }
    4064              : 
    4065              : // Whether the overall statement may fall through.
    4066              : 
    4067              : bool
    4068          342 : If_statement::do_may_fall_through() const
    4069              : {
    4070          342 :   return (this->else_block_ == NULL
    4071          329 :           || this->then_block_->may_fall_through()
    4072          670 :           || this->else_block_->may_fall_through());
    4073              : }
    4074              : 
    4075              : // Get the backend representation.
    4076              : 
    4077              : Bstatement*
    4078       698859 : If_statement::do_get_backend(Translate_context* context)
    4079              : {
    4080       698859 :   go_assert(this->cond_->type()->is_boolean_type()
    4081              :              || this->cond_->type()->is_error());
    4082       698859 :   Bexpression* cond = this->cond_->get_backend(context);
    4083       698859 :   Bblock* then_block = this->then_block_->get_backend(context);
    4084       698859 :   Bblock* else_block = (this->else_block_ == NULL
    4085       698859 :                         ? NULL
    4086       235592 :                         : this->else_block_->get_backend(context));
    4087       698859 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    4088       698859 :   return context->backend()->if_statement(bfunction,
    4089              :                                           cond, then_block, else_block,
    4090       698859 :                                           this->location());
    4091              : }
    4092              : 
    4093              : // Export an if statement.
    4094              : 
    4095              : void
    4096         4529 : If_statement::do_export_statement(Export_function_body* efb)
    4097              : {
    4098         4529 :   efb->write_c_string("if ");
    4099         4529 :   this->cond_->export_expression(efb);
    4100         4529 :   efb->write_c_string(" ");
    4101         4529 :   Block_statement::export_block(efb, this->then_block_, false);
    4102         4529 :   if (this->else_block_ != NULL)
    4103              :     {
    4104           70 :       efb->write_c_string(" else ");
    4105           70 :       Block_statement::export_block(efb, this->else_block_, false);
    4106              :     }
    4107         4529 : }
    4108              : 
    4109              : // Import an if statement.
    4110              : 
    4111              : Statement*
    4112         5427 : If_statement::do_import(Import_function_body* ifb, Location loc)
    4113              : {
    4114         5427 :   ifb->require_c_string("if ");
    4115              : 
    4116         5427 :   Expression* cond = Expression::import_expression(ifb, loc);
    4117         5427 :   ifb->require_c_string(" ");
    4118              : 
    4119         5427 :   if (!ifb->match_c_string("{"))
    4120              :     {
    4121            0 :       if (!ifb->saw_error())
    4122            0 :         go_error_at(ifb->location(),
    4123              :                     "import error for %qs: no block for if statement at %lu",
    4124            0 :                     ifb->name().c_str(),
    4125            0 :                     static_cast<unsigned long>(ifb->off()));
    4126            0 :       ifb->set_saw_error();
    4127            0 :       return Statement::make_error_statement(loc);
    4128              :     }
    4129              : 
    4130         5427 :   bool is_lowered_for_statement;
    4131         5427 :   Block* then_block = Block_statement::do_import(ifb, loc,
    4132              :                                                  &is_lowered_for_statement);
    4133         5427 :   if (then_block == NULL)
    4134            0 :     return Statement::make_error_statement(loc);
    4135         5427 :   if (is_lowered_for_statement)
    4136              :     {
    4137            0 :       if (!ifb->saw_error())
    4138            0 :         go_error_at(ifb->location(),
    4139              :                     ("import error for %qs: "
    4140              :                      "unexpected lowered for in if statement at %lu"),
    4141            0 :                     ifb->name().c_str(),
    4142            0 :                     static_cast<unsigned long>(ifb->off()));
    4143            0 :       ifb->set_saw_error();
    4144            0 :       return Statement::make_error_statement(loc);
    4145              :     }
    4146              : 
    4147         5427 :   Block* else_block = NULL;
    4148         5427 :   if (ifb->match_c_string(" else "))
    4149              :     {
    4150          136 :       ifb->advance(6);
    4151          136 :       if (!ifb->match_c_string("{"))
    4152              :         {
    4153            0 :           if (!ifb->saw_error())
    4154            0 :             go_error_at(ifb->location(),
    4155              :                         ("import error for %qs: no else block "
    4156              :                          "for if statement at %lu"),
    4157            0 :                         ifb->name().c_str(),
    4158            0 :                         static_cast<unsigned long>(ifb->off()));
    4159            0 :           ifb->set_saw_error();
    4160            0 :           return Statement::make_error_statement(loc);
    4161              :         }
    4162              : 
    4163          136 :       else_block = Block_statement::do_import(ifb, loc,
    4164              :                                               &is_lowered_for_statement);
    4165          136 :       if (else_block == NULL)
    4166            0 :         return Statement::make_error_statement(loc);
    4167          136 :       if (is_lowered_for_statement)
    4168              :         {
    4169            0 :           if (!ifb->saw_error())
    4170            0 :             go_error_at(ifb->location(),
    4171              :                         ("import error for %qs: "
    4172              :                          "unexpected lowered for in if statement at %lu"),
    4173            0 :                         ifb->name().c_str(),
    4174            0 :                         static_cast<unsigned long>(ifb->off()));
    4175            0 :           ifb->set_saw_error();
    4176            0 :           return Statement::make_error_statement(loc);
    4177              :         }
    4178              :     }
    4179              : 
    4180         5427 :   return Statement::make_if_statement(cond, then_block, else_block, loc);
    4181              : }
    4182              : 
    4183              : // Dump the AST representation for an if statement
    4184              : 
    4185              : void
    4186            0 : If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    4187              : {
    4188            0 :   ast_dump_context->print_indent();
    4189            0 :   ast_dump_context->ostream() << "if ";
    4190            0 :   ast_dump_context->dump_expression(this->cond_);
    4191            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    4192            0 :   if (ast_dump_context->dump_subblocks())
    4193              :     {
    4194            0 :       ast_dump_context->dump_block(this->then_block_);
    4195            0 :       if (this->else_block_ != NULL)
    4196              :         {
    4197            0 :           ast_dump_context->print_indent();
    4198            0 :           ast_dump_context->ostream() << "else" << std::endl;
    4199            0 :           ast_dump_context->dump_block(this->else_block_);
    4200              :         }
    4201              :     }
    4202            0 : }
    4203              : 
    4204              : // Make an if statement.
    4205              : 
    4206              : Statement*
    4207       704198 : Statement::make_if_statement(Expression* cond, Block* then_block,
    4208              :                              Block* else_block, Location location)
    4209              : {
    4210       704198 :   return new If_statement(cond, then_block, else_block, location);
    4211              : }
    4212              : 
    4213              : // Class Case_clauses::Hash_integer_value.
    4214              : 
    4215              : class Case_clauses::Hash_integer_value
    4216              : {
    4217              :  public:
    4218              :   size_t
    4219              :   operator()(Expression*) const;
    4220              : };
    4221              : 
    4222              : size_t
    4223        33164 : Case_clauses::Hash_integer_value::operator()(Expression* pe) const
    4224              : {
    4225        33164 :   Numeric_constant nc;
    4226        33164 :   mpz_t ival;
    4227        33164 :   if (!pe->numeric_constant_value(&nc) || !nc.to_int(&ival))
    4228            0 :     go_unreachable();
    4229        33164 :   size_t ret = mpz_get_ui(ival);
    4230        33164 :   mpz_clear(ival);
    4231        66328 :   return ret;
    4232        33164 : }
    4233              : 
    4234              : // Class Case_clauses::Eq_integer_value.
    4235              : 
    4236              : class Case_clauses::Eq_integer_value
    4237              : {
    4238              :  public:
    4239              :   bool
    4240              :   operator()(Expression*, Expression*) const;
    4241              : };
    4242              : 
    4243              : bool
    4244           47 : Case_clauses::Eq_integer_value::operator()(Expression* a, Expression* b) const
    4245              : {
    4246           47 :   Numeric_constant anc;
    4247           47 :   mpz_t aval;
    4248           47 :   Numeric_constant bnc;
    4249           47 :   mpz_t bval;
    4250           47 :   if (!a->numeric_constant_value(&anc)
    4251           47 :       || !anc.to_int(&aval)
    4252           47 :       || !b->numeric_constant_value(&bnc)
    4253           94 :       || !bnc.to_int(&bval))
    4254            0 :     go_unreachable();
    4255           47 :   bool ret = mpz_cmp(aval, bval) == 0;
    4256           47 :   mpz_clear(aval);
    4257           47 :   mpz_clear(bval);
    4258           94 :   return ret;
    4259           47 : }
    4260              : 
    4261              : // Class Case_clauses::Case_clause.
    4262              : 
    4263              : // Traversal.
    4264              : 
    4265              : int
    4266       668704 : Case_clauses::Case_clause::traverse(Traverse* traverse)
    4267              : {
    4268       668704 :   if (this->cases_ != NULL
    4269       668704 :       && (traverse->traverse_mask()
    4270       588252 :           & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
    4271              :     {
    4272       463414 :       if (this->cases_->traverse(traverse) == TRAVERSE_EXIT)
    4273              :         return TRAVERSE_EXIT;
    4274              :     }
    4275       668704 :   if (this->statements_ != NULL)
    4276              :     {
    4277       652097 :       if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
    4278              :         return TRAVERSE_EXIT;
    4279              :     }
    4280              :   return TRAVERSE_CONTINUE;
    4281              : }
    4282              : 
    4283              : // Check whether all the case expressions are integer constants.
    4284              : 
    4285              : bool
    4286        23577 : Case_clauses::Case_clause::is_constant() const
    4287              : {
    4288        23577 :   if (this->cases_ != NULL)
    4289              :     {
    4290        20882 :       for (Expression_list::const_iterator p = this->cases_->begin();
    4291        54158 :            p != this->cases_->end();
    4292        33276 :            ++p)
    4293        66617 :         if (!(*p)->is_constant() || (*p)->type()->integer_type() == NULL)
    4294           65 :           return false;
    4295              :     }
    4296              :   return true;
    4297              : }
    4298              : 
    4299              : // Lower a case clause for a nonconstant switch.  VAL_TEMP is the
    4300              : // value we are switching on; it may be NULL.  If START_LABEL is not
    4301              : // NULL, it goes at the start of the statements, after the condition
    4302              : // test.  We branch to FINISH_LABEL at the end of the statements.
    4303              : 
    4304              : void
    4305        16686 : Case_clauses::Case_clause::lower(Gogo* gogo, Block* b,
    4306              :                                  Temporary_statement* val_temp,
    4307              :                                  Unnamed_label* start_label,
    4308              :                                  Unnamed_label* finish_label) const
    4309              : {
    4310        16686 :   Location loc = this->location_;
    4311        16686 :   Unnamed_label* next_case_label;
    4312        16686 :   if (this->cases_ == NULL || this->cases_->empty())
    4313              :     {
    4314         2671 :       go_assert(this->is_default_);
    4315              :       next_case_label = NULL;
    4316              :     }
    4317              :   else
    4318              :     {
    4319              :       Expression* cond = NULL;
    4320              : 
    4321        17902 :       for (Expression_list::const_iterator p = this->cases_->begin();
    4322        31917 :            p != this->cases_->end();
    4323        17902 :            ++p)
    4324              :         {
    4325        17902 :           Expression* ref = Expression::make_temporary_reference(val_temp,
    4326              :                                                                  loc);
    4327        35804 :           Expression* this_cond = Expression::make_binary(OPERATOR_EQEQ, ref,
    4328        17902 :                                                           *p, loc);
    4329        17902 :           if (cond == NULL)
    4330              :             cond = this_cond;
    4331              :           else
    4332         3887 :             cond = Expression::make_binary(OPERATOR_OROR, cond, this_cond, loc);
    4333              :         }
    4334              : 
    4335        14015 :       Block* then_block = new Block(b, loc);
    4336        14015 :       next_case_label = new Unnamed_label(Linemap::unknown_location());
    4337        14015 :       Statement* s = Statement::make_goto_unnamed_statement(next_case_label,
    4338              :                                                             loc);
    4339        14015 :       then_block->add_statement(s);
    4340              : 
    4341              :       // if !COND { goto NEXT_CASE_LABEL }
    4342        14015 :       cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
    4343        14015 :       s = Statement::make_if_statement(cond, then_block, NULL, loc);
    4344        14015 :       s->determine_types(gogo);
    4345        14015 :       b->add_statement(s);
    4346              :     }
    4347              : 
    4348        16686 :   if (start_label != NULL)
    4349          115 :     b->add_statement(Statement::make_unnamed_label_statement(start_label));
    4350              : 
    4351        16686 :   if (this->statements_ != NULL)
    4352        15974 :     b->add_statement(Statement::make_block_statement(this->statements_, loc));
    4353              : 
    4354        16686 :   Statement* s = Statement::make_goto_unnamed_statement(finish_label, loc);
    4355        16686 :   b->add_statement(s);
    4356              : 
    4357        16686 :   if (next_case_label != NULL)
    4358        14015 :     b->add_statement(Statement::make_unnamed_label_statement(next_case_label));
    4359        16686 : }
    4360              : 
    4361              : // Determine types.
    4362              : 
    4363              : void
    4364        40214 : Case_clauses::Case_clause::determine_types(Gogo* gogo, Type* type)
    4365              : {
    4366        40214 :   if (this->cases_ != NULL)
    4367              :     {
    4368        34843 :       Type_context case_context(type, false);
    4369        85934 :       for (Expression_list::iterator p = this->cases_->begin();
    4370        85934 :            p != this->cases_->end();
    4371        51091 :            ++p)
    4372        51091 :         (*p)->determine_type(gogo, &case_context);
    4373              :     }
    4374        40214 :   if (this->statements_ != NULL)
    4375        38955 :     this->statements_->determine_types(gogo);
    4376        40214 : }
    4377              : 
    4378              : // Check types.  Returns false if there was an error.
    4379              : 
    4380              : bool
    4381        40210 : Case_clauses::Case_clause::check_types(Type* type)
    4382              : {
    4383        40210 :   if (this->cases_ != NULL)
    4384              :     {
    4385        34841 :       for (Expression_list::iterator p = this->cases_->begin();
    4386        85922 :            p != this->cases_->end();
    4387        51081 :            ++p)
    4388              :         {
    4389        51089 :           std::string reason;
    4390        51089 :           if (!Type::are_compatible_for_comparison(true, type, (*p)->type(),
    4391              :                                                    &reason))
    4392              :             {
    4393            8 :               go_error_at(this->location_, "%s", reason.c_str());
    4394            8 :               return false;
    4395              :             }
    4396        51089 :         }
    4397              :     }
    4398              :   return true;
    4399              : }
    4400              : 
    4401              : // Return true if this clause may fall through to the following
    4402              : // statements.  Note that this is not the same as whether the case
    4403              : // uses the "fallthrough" keyword.
    4404              : 
    4405              : bool
    4406         4442 : Case_clauses::Case_clause::may_fall_through() const
    4407              : {
    4408         4442 :   if (this->statements_ == NULL)
    4409              :     return true;
    4410         4433 :   return this->statements_->may_fall_through();
    4411              : }
    4412              : 
    4413              : // Convert the case values and statements to the backend
    4414              : // representation.  BREAK_LABEL is the label which break statements
    4415              : // should branch to.  CASE_CONSTANTS is used to detect duplicate
    4416              : // constants.  *CASES should be passed as an empty vector; the values
    4417              : // for this case will be added to it.  If this is the default case,
    4418              : // *CASES will remain empty.  This returns the statement to execute if
    4419              : // one of these cases is selected.
    4420              : 
    4421              : Bstatement*
    4422        23489 : Case_clauses::Case_clause::get_backend(Translate_context* context,
    4423              :                                        Unnamed_label* break_label,
    4424              :                                        Case_constants* case_constants,
    4425              :                                        std::vector<Bexpression*>* cases) const
    4426              : {
    4427        23489 :   if (this->cases_ != NULL)
    4428              :     {
    4429        20803 :       go_assert(!this->is_default_);
    4430        53967 :       for (Expression_list::const_iterator p = this->cases_->begin();
    4431        53967 :            p != this->cases_->end();
    4432        33164 :            ++p)
    4433              :         {
    4434        33164 :           Expression* e = *p;
    4435        33164 :           if (e->classification() != Expression::EXPRESSION_INTEGER)
    4436              :             {
    4437        23741 :               Numeric_constant nc;
    4438        23741 :               mpz_t ival;
    4439        23741 :               if (!(*p)->numeric_constant_value(&nc) || !nc.to_int(&ival))
    4440              :                 {
    4441              :                   // Something went wrong.  This can happen with a
    4442              :                   // negative constant and an unsigned switch value.
    4443            0 :                   go_assert(saw_errors());
    4444            0 :                   continue;
    4445              :                 }
    4446        23741 :               go_assert(nc.type() != NULL);
    4447        23741 :               e = Expression::make_integer_z(&ival, nc.type(), e->location());
    4448        23741 :               mpz_clear(ival);
    4449        23741 :             }
    4450              : 
    4451        33164 :           std::pair<Case_constants::iterator, bool> ins =
    4452        33164 :             case_constants->insert(e);
    4453        33164 :           if (!ins.second)
    4454              :             {
    4455              :               // Value was already present.
    4456            3 :               go_error_at(this->location_, "duplicate case in switch");
    4457            3 :               e = Expression::make_error(this->location_);
    4458              :             }
    4459        33164 :           cases->push_back(e->get_backend(context));
    4460              :         }
    4461              :     }
    4462              : 
    4463        23489 :   Bstatement* statements;
    4464        23489 :   if (this->statements_ == NULL)
    4465              :     statements = NULL;
    4466              :   else
    4467              :     {
    4468        22967 :       Bblock* bblock = this->statements_->get_backend(context);
    4469        22967 :       statements = context->backend()->block_statement(bblock);
    4470              :     }
    4471              : 
    4472        23489 :   Bstatement* break_stat;
    4473        23489 :   if (this->is_fallthrough_)
    4474              :     break_stat = NULL;
    4475              :   else
    4476        23128 :     break_stat = break_label->get_goto(context, this->location_);
    4477              : 
    4478        23489 :   if (statements == NULL)
    4479              :     return break_stat;
    4480        22967 :   else if (break_stat == NULL)
    4481              :     return statements;
    4482              :   else
    4483        22625 :     return context->backend()->compound_statement(statements, break_stat);
    4484              : }
    4485              : 
    4486              : // Dump the AST representation for a case clause
    4487              : 
    4488              : void
    4489            0 : Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context)
    4490              :     const
    4491              : {
    4492            0 :   ast_dump_context->print_indent();
    4493            0 :   if (this->is_default_)
    4494              :     {
    4495            0 :       ast_dump_context->ostream() << "default:";
    4496              :     }
    4497              :   else
    4498              :     {
    4499            0 :       ast_dump_context->ostream() << "case ";
    4500            0 :       ast_dump_context->dump_expression_list(this->cases_);
    4501            0 :       ast_dump_context->ostream() << ":" ;
    4502              :     }
    4503            0 :   ast_dump_context->dump_block(this->statements_);
    4504            0 :   if (this->is_fallthrough_)
    4505              :     {
    4506            0 :       ast_dump_context->print_indent();
    4507            0 :       ast_dump_context->ostream() <<  " (fallthrough)" << dsuffix(location()) << std::endl;
    4508              :     }
    4509            0 : }
    4510              : 
    4511              : // Class Case_clauses.
    4512              : 
    4513              : // Traversal.
    4514              : 
    4515              : int
    4516       172198 : Case_clauses::traverse(Traverse* traverse)
    4517              : {
    4518       840902 :   for (Clauses::iterator p = this->clauses_.begin();
    4519       840902 :        p != this->clauses_.end();
    4520       668704 :        ++p)
    4521              :     {
    4522       668704 :       if (p->traverse(traverse) == TRAVERSE_EXIT)
    4523       172198 :         return TRAVERSE_EXIT;
    4524              :     }
    4525              :   return TRAVERSE_CONTINUE;
    4526              : }
    4527              : 
    4528              : // Check whether all the case expressions are constant.
    4529              : 
    4530              : bool
    4531         5916 : Case_clauses::is_constant() const
    4532              : {
    4533        29428 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4534        29428 :        p != this->clauses_.end();
    4535        23512 :        ++p)
    4536        23577 :     if (!p->is_constant())
    4537         5916 :       return false;
    4538              :   return true;
    4539              : }
    4540              : 
    4541              : // Lower case clauses for a nonconstant switch.
    4542              : 
    4543              : void
    4544         5301 : Case_clauses::lower(Gogo* gogo, Block* b, Temporary_statement* val_temp,
    4545              :                     Unnamed_label* break_label) const
    4546              : {
    4547              :   // The default case.
    4548         5301 :   const Case_clause* default_case = NULL;
    4549              : 
    4550              :   // The label for the fallthrough of the previous case.
    4551         5301 :   Unnamed_label* last_fallthrough_label = NULL;
    4552              : 
    4553              :   // The label for the start of the default case.  This is used if the
    4554              :   // case before the default case falls through.
    4555         5301 :   Unnamed_label* default_start_label = NULL;
    4556              : 
    4557              :   // The label for the end of the default case.  This normally winds
    4558              :   // up as BREAK_LABEL, but it will be different if the default case
    4559              :   // falls through.
    4560         5301 :   Unnamed_label* default_finish_label = NULL;
    4561              : 
    4562        21987 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4563        21987 :        p != this->clauses_.end();
    4564        16686 :        ++p)
    4565              :     {
    4566              :       // The label to use for the start of the statements for this
    4567              :       // case.  This is NULL unless the previous case falls through.
    4568        16686 :       Unnamed_label* start_label = last_fallthrough_label;
    4569              : 
    4570              :       // The label to jump to after the end of the statements for this
    4571              :       // case.
    4572        16686 :       Unnamed_label* finish_label = break_label;
    4573              : 
    4574        16686 :       last_fallthrough_label = NULL;
    4575        16686 :       if (p->is_fallthrough() && p + 1 != this->clauses_.end())
    4576              :         {
    4577          115 :           finish_label = new Unnamed_label(p->location());
    4578          115 :           last_fallthrough_label = finish_label;
    4579              :         }
    4580              : 
    4581        16686 :       if (!p->is_default())
    4582        14015 :         p->lower(gogo, b, val_temp, start_label, finish_label);
    4583              :       else
    4584              :         {
    4585              :           // We have to move the default case to the end, so that we
    4586              :           // only use it if all the other tests fail.
    4587              :           default_case = &*p;
    4588              :           default_start_label = start_label;
    4589              :           default_finish_label = finish_label;
    4590              :         }
    4591              :     }
    4592              : 
    4593         5301 :   if (default_case != NULL)
    4594         2671 :     default_case->lower(gogo, b, val_temp, default_start_label,
    4595              :                         default_finish_label);
    4596         5301 : }
    4597              : 
    4598              : // Determine types.
    4599              : 
    4600              : void
    4601        11185 : Case_clauses::determine_types(Gogo* gogo, Type* type)
    4602              : {
    4603        51399 :   for (Clauses::iterator p = this->clauses_.begin();
    4604        51399 :        p != this->clauses_.end();
    4605        40214 :        ++p)
    4606        40214 :     p->determine_types(gogo, type);
    4607        11185 : }
    4608              : 
    4609              : // Check types.  Returns false if there was an error.
    4610              : 
    4611              : bool
    4612        11182 : Case_clauses::check_types(Type* type)
    4613              : {
    4614        11182 :   bool ret = true;
    4615        51392 :   for (Clauses::iterator p = this->clauses_.begin();
    4616        51392 :        p != this->clauses_.end();
    4617        40210 :        ++p)
    4618              :     {
    4619        40210 :       if (!p->check_types(type))
    4620            8 :         ret = false;
    4621              :     }
    4622        11182 :   return ret;
    4623              : }
    4624              : 
    4625              : // Return true if these clauses may fall through to the statements
    4626              : // following the switch statement.
    4627              : 
    4628              : bool
    4629         1011 : Case_clauses::may_fall_through() const
    4630              : {
    4631         1011 :   bool found_default = false;
    4632         5453 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4633         5453 :        p != this->clauses_.end();
    4634         4442 :        ++p)
    4635              :     {
    4636         4442 :       if (p->may_fall_through() && !p->is_fallthrough())
    4637         1011 :         return true;
    4638         4442 :       if (p->is_default())
    4639          987 :         found_default = true;
    4640              :     }
    4641         1011 :   return !found_default;
    4642              : }
    4643              : 
    4644              : // Convert the cases to the backend representation.  This sets
    4645              : // *ALL_CASES and *ALL_STATEMENTS.
    4646              : 
    4647              : void
    4648         5840 : Case_clauses::get_backend(Translate_context* context,
    4649              :                           Unnamed_label* break_label,
    4650              :                           std::vector<std::vector<Bexpression*> >* all_cases,
    4651              :                           std::vector<Bstatement*>* all_statements) const
    4652              : {
    4653         5840 :   Case_constants case_constants;
    4654              : 
    4655         5840 :   size_t c = this->clauses_.size();
    4656         5840 :   all_cases->resize(c);
    4657         5840 :   all_statements->resize(c);
    4658              : 
    4659         5840 :   size_t i = 0;
    4660         5840 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4661        29329 :        p != this->clauses_.end();
    4662        23489 :        ++p, ++i)
    4663              :     {
    4664        23489 :       std::vector<Bexpression*> cases;
    4665        23489 :       Bstatement* stat = p->get_backend(context, break_label, &case_constants,
    4666              :                                         &cases);
    4667              :       // The final clause can't fall through.
    4668        23489 :       if (i == c - 1 && p->is_fallthrough())
    4669              :         {
    4670            2 :           go_assert(saw_errors());
    4671            2 :           stat = context->backend()->error_statement();
    4672              :         }
    4673        23489 :       (*all_cases)[i].swap(cases);
    4674        23489 :       (*all_statements)[i] = stat;
    4675        23489 :     }
    4676         5840 : }
    4677              : 
    4678              : // Dump the AST representation for case clauses (from a switch statement)
    4679              : 
    4680              : void
    4681            0 : Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
    4682              : {
    4683            0 :   for (Clauses::const_iterator p = this->clauses_.begin();
    4684            0 :        p != this->clauses_.end();
    4685            0 :        ++p)
    4686            0 :     p->dump_clause(ast_dump_context);
    4687            0 : }
    4688              : 
    4689              : // A constant switch statement.  A Switch_statement is lowered to this
    4690              : // when all the cases are constants.
    4691              : 
    4692              : class Constant_switch_statement : public Statement
    4693              : {
    4694              :  public:
    4695         5851 :   Constant_switch_statement(Expression* val, Case_clauses* clauses,
    4696              :                             Unnamed_label* break_label,
    4697              :                             Location location)
    4698         5851 :     : Statement(STATEMENT_CONSTANT_SWITCH, location),
    4699        11702 :       val_(val), clauses_(clauses), break_label_(break_label)
    4700              :   { }
    4701              : 
    4702              :  protected:
    4703              :   int
    4704              :   do_traverse(Traverse*);
    4705              : 
    4706              :   Bstatement*
    4707              :   do_get_backend(Translate_context*);
    4708              : 
    4709              :   void
    4710              :   do_dump_statement(Ast_dump_context*) const;
    4711              : 
    4712              :  private:
    4713              :   // The value to switch on.
    4714              :   Expression* val_;
    4715              :   // The case clauses.
    4716              :   Case_clauses* clauses_;
    4717              :   // The break label, if needed.
    4718              :   Unnamed_label* break_label_;
    4719              : };
    4720              : 
    4721              : // Traversal.
    4722              : 
    4723              : int
    4724       138161 : Constant_switch_statement::do_traverse(Traverse* traverse)
    4725              : {
    4726       138161 :   if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
    4727              :     return TRAVERSE_EXIT;
    4728       116283 :   return this->clauses_->traverse(traverse);
    4729              : }
    4730              : 
    4731              : // Convert to GENERIC.
    4732              : 
    4733              : Bstatement*
    4734         5840 : Constant_switch_statement::do_get_backend(Translate_context* context)
    4735              : {
    4736         5840 :   Bexpression* switch_val_expr = this->val_->get_backend(context);
    4737              : 
    4738         5840 :   Unnamed_label* break_label = this->break_label_;
    4739         5840 :   if (break_label == NULL)
    4740         5497 :     break_label = new Unnamed_label(this->location());
    4741              : 
    4742         5840 :   std::vector<std::vector<Bexpression*> > all_cases;
    4743         5840 :   std::vector<Bstatement*> all_statements;
    4744         5840 :   this->clauses_->get_backend(context, break_label, &all_cases,
    4745              :                               &all_statements);
    4746              : 
    4747         5840 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    4748         5840 :   Bstatement* switch_statement;
    4749         5840 :   switch_statement = context->backend()->switch_statement(bfunction,
    4750              :                                                           switch_val_expr,
    4751              :                                                           all_cases,
    4752              :                                                           all_statements,
    4753              :                                                           this->location());
    4754         5840 :   Bstatement* ldef = break_label->get_definition(context);
    4755         5840 :   return context->backend()->compound_statement(switch_statement, ldef);
    4756         5840 : }
    4757              : 
    4758              : // Dump the AST representation for a constant switch statement.
    4759              : 
    4760              : void
    4761            0 : Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    4762              :     const
    4763              : {
    4764            0 :   ast_dump_context->print_indent();
    4765            0 :   ast_dump_context->ostream() << "switch ";
    4766            0 :   ast_dump_context->dump_expression(this->val_);
    4767              : 
    4768            0 :   if (ast_dump_context->dump_subblocks())
    4769              :     {
    4770            0 :       ast_dump_context->ostream() << " {" << std::endl;
    4771            0 :       this->clauses_->dump_clauses(ast_dump_context);
    4772            0 :       ast_dump_context->ostream() << "}";
    4773              :     }
    4774              : 
    4775            0 :    ast_dump_context->ostream() << std::endl;
    4776            0 : }
    4777              : 
    4778              : // Class Switch_statement.
    4779              : 
    4780              : // Traversal.
    4781              : 
    4782              : int
    4783        55915 : Switch_statement::do_traverse(Traverse* traverse)
    4784              : {
    4785        55915 :   if (this->val_ != NULL)
    4786              :     {
    4787        40790 :       if (this->traverse_expression(traverse, &this->val_) == TRAVERSE_EXIT)
    4788              :         return TRAVERSE_EXIT;
    4789              :     }
    4790        55915 :   return this->clauses_->traverse(traverse);
    4791              : }
    4792              : 
    4793              : void
    4794        11185 : Switch_statement::do_determine_types(Gogo* gogo)
    4795              : {
    4796        11185 :   if (this->val_ != NULL)
    4797         8160 :     this->val_->determine_type_no_context(gogo);
    4798        11185 :   this->clauses_->determine_types(gogo,
    4799        11185 :                                   (this->val_ == NULL
    4800              :                                    ? NULL
    4801         8160 :                                    : this->val_->type()));
    4802        11185 : }
    4803              : 
    4804              : void
    4805        11185 : Switch_statement::do_check_types(Gogo*)
    4806              : {
    4807        11185 :   if (this->val_ != NULL
    4808        11185 :       && (this->val_->is_error_expression()
    4809         8160 :           || this->val_->type()->is_error()))
    4810            1 :     return;
    4811              : 
    4812        11184 :   if (this->val_ != NULL
    4813         8159 :       && !this->val_->type()->is_comparable()
    4814        11195 :       && !Type::are_compatible_for_comparison(true, this->val_->type(),
    4815           11 :                                               Type::make_nil_type(), NULL))
    4816              :     {
    4817            2 :       go_error_at(this->val_->location(),
    4818              :                   "cannot switch on value whose type may not be compared");
    4819            2 :       this->set_is_error();
    4820            2 :       return;
    4821              :     }
    4822              : 
    4823        11182 :   Type* type;
    4824        11182 :   if (this->val_ != NULL)
    4825         8157 :     type = this->val_->type();
    4826              :   else
    4827         3025 :     type = Type::make_boolean_type();
    4828        11182 :   if (!this->clauses_->check_types(type))
    4829            8 :     this->set_is_error();
    4830              : }
    4831              : 
    4832              : // Lower a Switch_statement to a Constant_switch_statement or a series
    4833              : // of if statements.
    4834              : 
    4835              : Statement*
    4836        11175 : Switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
    4837              :                            Statement_inserter*)
    4838              : {
    4839        11175 :   Location loc = this->location();
    4840              : 
    4841        11175 :   if (this->val_ != NULL
    4842        11175 :       && (this->val_->is_error_expression()
    4843         8150 :           || this->val_->type()->is_error()))
    4844              :     {
    4845            1 :       go_assert(saw_errors());
    4846            1 :       return Statement::make_error_statement(loc);
    4847              :     }
    4848              : 
    4849        11174 :   if (this->val_ != NULL
    4850         8149 :       && this->val_->type()->integer_type() != NULL
    4851         5917 :       && !this->clauses_->empty()
    4852        17090 :       && this->clauses_->is_constant())
    4853         5851 :     return new Constant_switch_statement(this->val_, this->clauses_,
    4854         5851 :                                          this->break_label_, loc);
    4855              : 
    4856         5323 :   Block* b = new Block(enclosing, loc);
    4857              : 
    4858         5323 :   if (this->clauses_->empty())
    4859              :     {
    4860           22 :       Expression* val = this->val_;
    4861           22 :       if (val == NULL)
    4862           13 :         val = Expression::make_boolean(true, loc);
    4863           22 :       return Statement::make_statement(val, true);
    4864              :     }
    4865              : 
    4866              :   // var val_temp VAL_TYPE = VAL
    4867         5301 :   Expression* val = this->val_;
    4868         5301 :   if (val == NULL)
    4869         3012 :     val = Expression::make_boolean(true, loc);
    4870              : 
    4871         5301 :   Type* type = val->type();
    4872         5301 :   if (type->is_abstract())
    4873         3012 :     type = type->make_non_abstract_type();
    4874         5301 :   Temporary_statement* val_temp = Statement::make_temporary(type, val, loc);
    4875         5301 :   b->add_statement(val_temp);
    4876              : 
    4877         5301 :   this->clauses_->lower(gogo, b, val_temp, this->break_label());
    4878              : 
    4879         5301 :   Statement* s = Statement::make_unnamed_label_statement(this->break_label_);
    4880         5301 :   b->add_statement(s);
    4881              : 
    4882         5301 :   return Statement::make_block_statement(b, loc);
    4883              : }
    4884              : 
    4885              : // Return the break label for this switch statement, creating it if
    4886              : // necessary.
    4887              : 
    4888              : Unnamed_label*
    4889         6269 : Switch_statement::break_label()
    4890              : {
    4891         6269 :   if (this->break_label_ == NULL)
    4892         5644 :     this->break_label_ = new Unnamed_label(this->location());
    4893         6269 :   return this->break_label_;
    4894              : }
    4895              : 
    4896              : // Dump the AST representation for a switch statement.
    4897              : 
    4898              : void
    4899            0 : Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    4900              : {
    4901            0 :   ast_dump_context->print_indent();
    4902            0 :   ast_dump_context->ostream() << "switch ";
    4903            0 :   if (this->val_ != NULL)
    4904              :     {
    4905            0 :       ast_dump_context->dump_expression(this->val_);
    4906              :     }
    4907            0 :   if (ast_dump_context->dump_subblocks())
    4908              :     {
    4909            0 :       ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
    4910            0 :       this->clauses_->dump_clauses(ast_dump_context);
    4911            0 :       ast_dump_context->print_indent();
    4912            0 :       ast_dump_context->ostream() << "}";
    4913              :     }
    4914            0 :   ast_dump_context->ostream() << std::endl;
    4915            0 : }
    4916              : 
    4917              : // Return whether this switch may fall through.
    4918              : 
    4919              : bool
    4920         1023 : Switch_statement::do_may_fall_through() const
    4921              : {
    4922         1023 :   if (this->clauses_ == NULL)
    4923              :     return true;
    4924              : 
    4925              :   // If we have a break label, then some case needed it.  That implies
    4926              :   // that the switch statement as a whole can fall through.
    4927         1023 :   if (this->break_label_ != NULL)
    4928              :     return true;
    4929              : 
    4930         1011 :   return this->clauses_->may_fall_through();
    4931              : }
    4932              : 
    4933              : // Make a switch statement.
    4934              : 
    4935              : Switch_statement*
    4936        11186 : Statement::make_switch_statement(Expression* val, Location location)
    4937              : {
    4938        11186 :   return new Switch_statement(val, location);
    4939              : }
    4940              : 
    4941              : // Class Type_case_clauses::Type_case_clause.
    4942              : 
    4943              : // Traversal.
    4944              : 
    4945              : int
    4946        63273 : Type_case_clauses::Type_case_clause::traverse(Traverse* traverse)
    4947              : {
    4948        63273 :   if (!this->is_default_
    4949        58007 :       && ((traverse->traverse_mask()
    4950        58007 :            & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
    4951       121280 :       && Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
    4952              :     return TRAVERSE_EXIT;
    4953        63273 :   if (this->statements_ != NULL)
    4954        54592 :     return this->statements_->traverse(traverse);
    4955              :   return TRAVERSE_CONTINUE;
    4956              : }
    4957              : 
    4958              : void
    4959        12656 : Type_case_clauses::Type_case_clause::determine_types(Gogo* gogo)
    4960              : {
    4961        12656 :   if (this->statements_ != NULL)
    4962        10919 :     this->statements_->determine_types(gogo);
    4963        12656 : }
    4964              : 
    4965              : bool
    4966        12656 : Type_case_clauses::Type_case_clause::check_types(Type* switch_val_type)
    4967              : {
    4968        12656 :   if (!this->is_default_)
    4969              :     {
    4970        11602 :       Type* type = this->type_;
    4971        11602 :       std::string reason;
    4972        11602 :       if (switch_val_type->interface_type() != NULL
    4973        11600 :           && !type->is_nil_constant_as_type()
    4974        22697 :           && type->interface_type() == NULL
    4975        11096 :           && !switch_val_type->interface_type()->implements_interface(type,
    4976              :                                                                       &reason))
    4977              :         {
    4978            1 :           if (reason.empty())
    4979            0 :             go_error_at(this->location_, "impossible type switch case");
    4980              :           else
    4981            1 :             go_error_at(this->location_, "impossible type switch case (%s)",
    4982              :                         reason.c_str());
    4983            1 :           return false;
    4984              :         }
    4985        11602 :     }
    4986              :   return true;
    4987              : }
    4988              : 
    4989              : // Lower one clause in a type switch.  Add statements to the block B.
    4990              : // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
    4991              : // BREAK_LABEL is the label at the end of the type switch.
    4992              : // *STMTS_LABEL, if not NULL, is a label to put at the start of the
    4993              : // statements.
    4994              : 
    4995              : void
    4996        12649 : Type_case_clauses::Type_case_clause::lower(Gogo* gogo,
    4997              :                                            Block* b,
    4998              :                                            Temporary_statement* descriptor_temp,
    4999              :                                            Unnamed_label* break_label,
    5000              :                                            Unnamed_label** stmts_label) const
    5001              : {
    5002        12649 :   Location loc = this->location_;
    5003              : 
    5004        12649 :   Unnamed_label* next_case_label = NULL;
    5005        12649 :   if (!this->is_default_)
    5006              :     {
    5007        11599 :       Type* type = this->type_;
    5008              : 
    5009        11599 :       Expression* ref = Expression::make_temporary_reference(descriptor_temp,
    5010              :                                                              loc);
    5011              : 
    5012        11599 :       Expression* cond;
    5013              :       // The language permits case nil, which is of course a constant
    5014              :       // rather than a type.  It will appear here as an invalid
    5015              :       // forwarding type.
    5016        11599 :       if (type->is_nil_constant_as_type())
    5017          227 :         cond = Expression::make_binary(OPERATOR_EQEQ, ref,
    5018              :                                        Expression::make_nil(loc),
    5019              :                                        loc);
    5020        11372 :       else if (type->interface_type() == NULL)
    5021              :         {
    5022        11095 :           if (!gogo->need_eqtype())
    5023        11095 :             cond = Expression::make_binary(OPERATOR_EQEQ, ref,
    5024              :                                            Expression::make_type_descriptor(type, loc),
    5025              :                                            loc);
    5026              :           else
    5027            0 :             cond = Runtime::make_call(gogo, Runtime::EQTYPE, loc, 2,
    5028              :                                       Expression::make_type_descriptor(type, loc),
    5029              :                                       ref);
    5030              :         }
    5031              :       else
    5032          277 :         cond = Runtime::make_call(gogo, Runtime::IFACET2IP, loc, 2,
    5033              :                                   Expression::make_type_descriptor(type, loc),
    5034              :                                   ref);
    5035              : 
    5036        11599 :       Unnamed_label* dest;
    5037        11599 :       if (!this->is_fallthrough_)
    5038              :         {
    5039              :           // if !COND { goto NEXT_CASE_LABEL }
    5040        10321 :           next_case_label = new Unnamed_label(Linemap::unknown_location());
    5041        10321 :           dest = next_case_label;
    5042        10321 :           cond = Expression::make_unary(OPERATOR_NOT, cond, loc);
    5043              :         }
    5044              :       else
    5045              :         {
    5046              :           // if COND { goto STMTS_LABEL }
    5047         1278 :           go_assert(stmts_label != NULL);
    5048         1278 :           if (*stmts_label == NULL)
    5049          531 :             *stmts_label = new Unnamed_label(Linemap::unknown_location());
    5050         1278 :           dest = *stmts_label;
    5051              :         }
    5052        11599 :       Block* then_block = new Block(b, loc);
    5053        11599 :       Statement* s = Statement::make_goto_unnamed_statement(dest, loc);
    5054        11599 :       then_block->add_statement(s);
    5055        11599 :       s = Statement::make_if_statement(cond, then_block, NULL, loc);
    5056        11599 :       s->determine_types(gogo);
    5057        11599 :       b->add_statement(s);
    5058              :     }
    5059              : 
    5060        12649 :   if (this->statements_ != NULL
    5061         1733 :       || (!this->is_fallthrough_
    5062          455 :           && stmts_label != NULL
    5063          449 :           && *stmts_label != NULL))
    5064              :     {
    5065        10994 :       go_assert(!this->is_fallthrough_);
    5066        10994 :       if (stmts_label != NULL && *stmts_label != NULL)
    5067              :         {
    5068          531 :           go_assert(!this->is_default_);
    5069          531 :           if (this->statements_ != NULL)
    5070          453 :             (*stmts_label)->set_location(this->statements_->start_location());
    5071          531 :           Statement* s = Statement::make_unnamed_label_statement(*stmts_label);
    5072          531 :           b->add_statement(s);
    5073          531 :           *stmts_label = NULL;
    5074              :         }
    5075        10994 :       if (this->statements_ != NULL)
    5076        10916 :         b->add_statement(Statement::make_block_statement(this->statements_,
    5077              :                                                          loc));
    5078              :     }
    5079              : 
    5080        12649 :   if (this->is_fallthrough_)
    5081         1278 :     go_assert(next_case_label == NULL);
    5082              :   else
    5083              :     {
    5084        11371 :       Location gloc = (this->statements_ == NULL
    5085        11371 :                               ? loc
    5086        11371 :                               : this->statements_->end_location());
    5087        11371 :       b->add_statement(Statement::make_goto_unnamed_statement(break_label,
    5088              :                                                               gloc));
    5089        11371 :       if (next_case_label != NULL)
    5090              :         {
    5091        10321 :           Statement* s =
    5092        10321 :             Statement::make_unnamed_label_statement(next_case_label);
    5093        10321 :           b->add_statement(s);
    5094              :         }
    5095              :     }
    5096        12649 : }
    5097              : 
    5098              : // Return true if this type clause may fall through to the statements
    5099              : // following the switch.
    5100              : 
    5101              : bool
    5102          984 : Type_case_clauses::Type_case_clause::may_fall_through() const
    5103              : {
    5104          984 :   if (this->is_fallthrough_)
    5105              :     {
    5106              :       // This case means that we automatically fall through to the
    5107              :       // next case (it's used for T1 in case T1, T2:).  It does not
    5108              :       // mean that we fall through to the end of the type switch as a
    5109              :       // whole.  There is sure to be a next case and that next case
    5110              :       // will determine whether we fall through to the statements
    5111              :       // after the type switch.
    5112              :       return false;
    5113              :     }
    5114          901 :   if (this->statements_ == NULL)
    5115              :     return true;
    5116          901 :   return this->statements_->may_fall_through();
    5117              : }
    5118              : 
    5119              : // Dump the AST representation for a type case clause
    5120              : 
    5121              : void
    5122            0 : Type_case_clauses::Type_case_clause::dump_clause(
    5123              :     Ast_dump_context* ast_dump_context) const
    5124              : {
    5125            0 :   ast_dump_context->print_indent();
    5126            0 :   if (this->is_default_)
    5127              :     {
    5128            0 :       ast_dump_context->ostream() << "default:";
    5129              :     }
    5130              :   else
    5131              :     {
    5132            0 :       ast_dump_context->ostream() << "case ";
    5133            0 :       ast_dump_context->dump_type(this->type_);
    5134            0 :       ast_dump_context->ostream() << ":" ;
    5135              :     }
    5136            0 :   ast_dump_context->dump_block(this->statements_);
    5137            0 :   if (this->is_fallthrough_)
    5138              :     {
    5139            0 :       ast_dump_context->print_indent();
    5140            0 :       ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
    5141              :     }
    5142            0 : }
    5143              : 
    5144              : // Class Type_case_clauses.
    5145              : 
    5146              : // Traversal.
    5147              : 
    5148              : int
    5149        11958 : Type_case_clauses::traverse(Traverse* traverse)
    5150              : {
    5151        75231 :   for (Type_clauses::iterator p = this->clauses_.begin();
    5152        75231 :        p != this->clauses_.end();
    5153        63273 :        ++p)
    5154              :     {
    5155        63273 :       if (p->traverse(traverse) == TRAVERSE_EXIT)
    5156        11958 :         return TRAVERSE_EXIT;
    5157              :     }
    5158              :   return TRAVERSE_CONTINUE;
    5159              : }
    5160              : 
    5161              : void
    5162         2393 : Type_case_clauses::determine_types(Gogo* gogo)
    5163              : {
    5164        15049 :   for (Type_clauses::iterator p = this->clauses_.begin();
    5165        15049 :        p != this->clauses_.end();
    5166        12656 :        ++p)
    5167        12656 :     p->determine_types(gogo);
    5168         2393 : }
    5169              : 
    5170              : bool
    5171         2393 : Type_case_clauses::check_types(Type* switch_val_type)
    5172              : {
    5173         2393 :   bool ret = true;
    5174        15049 :   for (Type_clauses::iterator p = this->clauses_.begin();
    5175        15049 :        p != this->clauses_.end();
    5176        12656 :        ++p)
    5177              :     {
    5178        12656 :       if (!p->check_types(switch_val_type))
    5179            1 :         ret = false;
    5180              :     }
    5181         2393 :   return ret;
    5182              : }
    5183              : 
    5184              : // Check for duplicate types.
    5185              : 
    5186              : void
    5187         2393 : Type_case_clauses::check_duplicates() const
    5188              : {
    5189         2393 :   typedef Unordered_set_hash(const Type*, Type_hash_identical,
    5190              :                              Type_identical) Types_seen;
    5191         2393 :   Types_seen types_seen;
    5192        15049 :   for (Type_clauses::const_iterator p = this->clauses_.begin();
    5193        15049 :        p != this->clauses_.end();
    5194        12656 :        ++p)
    5195              :     {
    5196        12656 :       Type* t = p->type();
    5197        12656 :       if (t == NULL)
    5198         1054 :         continue;
    5199        11602 :       if (t->is_nil_constant_as_type())
    5200          227 :         t = Type::make_nil_type();
    5201        11602 :       std::pair<Types_seen::iterator, bool> ins = types_seen.insert(t);
    5202        11602 :       if (!ins.second)
    5203            6 :         go_error_at(p->location(), "duplicate type in switch");
    5204              :     }
    5205         2393 : }
    5206              : 
    5207              : // Lower the clauses in a type switch.  Add statements to the block B.
    5208              : // The type descriptor we are switching on is in DESCRIPTOR_TEMP.
    5209              : // BREAK_LABEL is the label at the end of the type switch.
    5210              : 
    5211              : void
    5212         2386 : Type_case_clauses::lower(Gogo* gogo, Block* b,
    5213              :                          Temporary_statement* descriptor_temp,
    5214              :                          Unnamed_label* break_label) const
    5215              : {
    5216         2386 :   const Type_case_clause* default_case = NULL;
    5217              : 
    5218         2386 :   Unnamed_label* stmts_label = NULL;
    5219        15035 :   for (Type_clauses::const_iterator p = this->clauses_.begin();
    5220        15035 :        p != this->clauses_.end();
    5221        12649 :        ++p)
    5222              :     {
    5223        12649 :       if (!p->is_default())
    5224        11599 :         p->lower(gogo, b, descriptor_temp, break_label, &stmts_label);
    5225              :       else
    5226              :         {
    5227              :           // We are generating a series of tests, which means that we
    5228              :           // need to move the default case to the end.
    5229              :           default_case = &*p;
    5230              :         }
    5231              :     }
    5232         2386 :   go_assert(stmts_label == NULL);
    5233              : 
    5234         2386 :   if (default_case != NULL)
    5235         1050 :     default_case->lower(gogo, b, descriptor_temp, break_label, NULL);
    5236         2386 : }
    5237              : 
    5238              : // Return true if these clauses may fall through to the statements
    5239              : // following the switch statement.
    5240              : 
    5241              : bool
    5242          203 : Type_case_clauses::may_fall_through() const
    5243              : {
    5244          203 :   bool found_default = false;
    5245         1187 :   for (Type_clauses::const_iterator p = this->clauses_.begin();
    5246         1187 :        p != this->clauses_.end();
    5247          984 :        ++p)
    5248              :     {
    5249          984 :       if (p->may_fall_through())
    5250          203 :         return true;
    5251          984 :       if (p->is_default())
    5252          191 :         found_default = true;
    5253              :     }
    5254          203 :   return !found_default;
    5255              : }
    5256              : 
    5257              : // Dump the AST representation for case clauses (from a switch statement)
    5258              : 
    5259              : void
    5260            0 : Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
    5261              : {
    5262            0 :   for (Type_clauses::const_iterator p = this->clauses_.begin();
    5263            0 :        p != this->clauses_.end();
    5264            0 :        ++p)
    5265            0 :     p->dump_clause(ast_dump_context);
    5266            0 : }
    5267              : 
    5268              : // Class Type_switch_statement.
    5269              : 
    5270              : // Traversal.
    5271              : 
    5272              : int
    5273        11958 : Type_switch_statement::do_traverse(Traverse* traverse)
    5274              : {
    5275        11958 :   if (this->traverse_expression(traverse, &this->expr_) == TRAVERSE_EXIT)
    5276              :     return TRAVERSE_EXIT;
    5277        11958 :   if (this->clauses_ != NULL)
    5278        11958 :     return this->clauses_->traverse(traverse);
    5279              :   return TRAVERSE_CONTINUE;
    5280              : }
    5281              : 
    5282              : void
    5283         2393 : Type_switch_statement::do_determine_types(Gogo* gogo)
    5284              : {
    5285         2393 :   this->expr_->determine_type_no_context(gogo);
    5286         2393 :   this->clauses_->determine_types(gogo);
    5287         2393 : }
    5288              : 
    5289              : void
    5290         2393 : Type_switch_statement::do_check_types(Gogo*)
    5291              : {
    5292         2393 :   if (this->clauses_ != NULL)
    5293         2393 :     this->clauses_->check_duplicates();
    5294              : 
    5295         2393 :   Type* expr_type = this->expr_->type();
    5296         2393 :   if (expr_type->interface_type() == NULL)
    5297              :     {
    5298            6 :       if (!expr_type->is_error())
    5299            4 :         this->report_error(_("cannot type switch on non-interface value"));
    5300            6 :       this->set_is_error();
    5301              :     }
    5302              : 
    5303         2393 :   if (!this->clauses_->check_types(expr_type))
    5304            1 :     this->set_is_error();
    5305         2393 : }
    5306              : 
    5307              : // Lower a type switch statement to a series of if statements.  The gc
    5308              : // compiler is able to generate a table in some cases.  However, that
    5309              : // does not work for us because we may have type descriptors in
    5310              : // different shared libraries, so we can't compare them with simple
    5311              : // equality testing.
    5312              : 
    5313              : Statement*
    5314         2386 : Type_switch_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
    5315              :                                 Statement_inserter*)
    5316              : {
    5317         2386 :   const Location loc = this->location();
    5318              : 
    5319         2386 :   if (this->classification() == STATEMENT_ERROR)
    5320            0 :     return Statement::make_error_statement(loc);
    5321              : 
    5322         2386 :   Block* b = new Block(enclosing, loc);
    5323              : 
    5324         2386 :   Temporary_statement* val_temp =
    5325         2386 :     Statement::make_temporary(NULL, this->expr_, loc);
    5326         2386 :   b->add_statement(val_temp);
    5327              : 
    5328              :   // var descriptor_temp DESCRIPTOR_TYPE
    5329         2386 :   Type* descriptor_type = Type::make_type_descriptor_ptr_type();
    5330         2386 :   Temporary_statement* descriptor_temp =
    5331         2386 :     Statement::make_temporary(descriptor_type, NULL, loc);
    5332         2386 :   b->add_statement(descriptor_temp);
    5333              : 
    5334              :   // descriptor_temp = ifacetype(val_temp)
    5335         2386 :   Expression* ref = Expression::make_temporary_reference(val_temp, loc);
    5336         2386 :   Expression* td = Expression::get_interface_type_descriptor(ref);
    5337         2386 :   Temporary_reference_expression* lhs =
    5338         2386 :     Expression::make_temporary_reference(descriptor_temp, loc);
    5339         2386 :   lhs->set_is_lvalue();
    5340         2386 :   Statement* s = Statement::make_assignment(lhs, td, loc);
    5341         2386 :   s->determine_types(gogo);
    5342         2386 :   b->add_statement(s);
    5343              : 
    5344         2386 :   if (this->clauses_ != NULL)
    5345         2386 :     this->clauses_->lower(gogo, b, descriptor_temp, this->break_label());
    5346              : 
    5347         2386 :   s = Statement::make_unnamed_label_statement(this->break_label_);
    5348         2386 :   b->add_statement(s);
    5349              : 
    5350         2386 :   return Statement::make_block_statement(b, loc);
    5351              : }
    5352              : 
    5353              : // Return whether this switch may fall through.
    5354              : 
    5355              : bool
    5356          215 : Type_switch_statement::do_may_fall_through() const
    5357              : {
    5358          215 :   if (this->clauses_ == NULL)
    5359              :     return true;
    5360              : 
    5361              :   // If we have a break label, then some case needed it.  That implies
    5362              :   // that the switch statement as a whole can fall through.
    5363          215 :   if (this->break_label_ != NULL)
    5364              :     return true;
    5365              : 
    5366          203 :   return this->clauses_->may_fall_through();
    5367              : }
    5368              : 
    5369              : // Return the break label for this type switch statement, creating it
    5370              : // if necessary.
    5371              : 
    5372              : Unnamed_label*
    5373         2583 : Type_switch_statement::break_label()
    5374              : {
    5375         2583 :   if (this->break_label_ == NULL)
    5376         2386 :     this->break_label_ = new Unnamed_label(this->location());
    5377         2583 :   return this->break_label_;
    5378              : }
    5379              : 
    5380              : // Dump the AST representation for a type switch statement
    5381              : 
    5382              : void
    5383            0 : Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
    5384              :     const
    5385              : {
    5386            0 :   ast_dump_context->print_indent();
    5387            0 :   ast_dump_context->ostream() << "switch ";
    5388            0 :   ast_dump_context->dump_expression(this->expr_);
    5389            0 :   ast_dump_context->ostream() << " .(type)";
    5390            0 :   if (ast_dump_context->dump_subblocks())
    5391              :     {
    5392            0 :       ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
    5393            0 :       this->clauses_->dump_clauses(ast_dump_context);
    5394            0 :       ast_dump_context->ostream() << "}";
    5395              :     }
    5396            0 :   ast_dump_context->ostream() << std::endl;
    5397            0 : }
    5398              : 
    5399              : // Make a type switch statement.
    5400              : 
    5401              : Type_switch_statement*
    5402         2393 : Statement::make_type_switch_statement(Expression* expr, Location location)
    5403              : {
    5404         2393 :   return new Type_switch_statement(expr, location);
    5405              : }
    5406              : 
    5407              : // Class Send_statement.
    5408              : 
    5409              : // Traversal.
    5410              : 
    5411              : int
    5412        60890 : Send_statement::do_traverse(Traverse* traverse)
    5413              : {
    5414        60890 :   if (this->traverse_expression(traverse, &this->channel_) == TRAVERSE_EXIT)
    5415              :     return TRAVERSE_EXIT;
    5416        59936 :   return this->traverse_expression(traverse, &this->val_);
    5417              : }
    5418              : 
    5419              : // Determine types.
    5420              : 
    5421              : void
    5422         2676 : Send_statement::do_determine_types(Gogo* gogo)
    5423              : {
    5424         2676 :   this->channel_->determine_type_no_context(gogo);
    5425         2676 :   Type* type = this->channel_->type();
    5426         2676 :   Type_context context;
    5427         2676 :   if (type->channel_type() != NULL)
    5428         5348 :     context.type = type->channel_type()->element_type();
    5429         2676 :   this->val_->determine_type(gogo, &context);
    5430         2676 : }
    5431              : 
    5432              : // Check types.
    5433              : 
    5434              : void
    5435         2594 : Send_statement::do_check_types(Gogo*)
    5436              : {
    5437         2594 :   Type* type = this->channel_->type();
    5438         2594 :   if (type->is_error())
    5439              :     {
    5440            1 :       this->set_is_error();
    5441            1 :       return;
    5442              :     }
    5443         2593 :   Channel_type* channel_type = type->channel_type();
    5444         2593 :   if (channel_type == NULL)
    5445              :     {
    5446            1 :       go_error_at(this->location(), "left operand of %<<-%> must be channel");
    5447            1 :       this->set_is_error();
    5448            1 :       return;
    5449              :     }
    5450         2592 :   Type* element_type = channel_type->element_type();
    5451         2592 :   if (!Type::are_assignable(element_type, this->val_->type(), NULL))
    5452              :     {
    5453            0 :       this->report_error(_("incompatible types in send"));
    5454            0 :       return;
    5455              :     }
    5456         2592 :   if (!channel_type->may_send())
    5457              :     {
    5458            1 :       this->report_error(_("invalid send on receive-only channel"));
    5459            1 :       return;
    5460              :     }
    5461              : }
    5462              : 
    5463              : // Flatten a send statement.  We may need a temporary for interface
    5464              : // conversion.
    5465              : 
    5466              : Statement*
    5467         2608 : Send_statement::do_flatten(Gogo*, Named_object*, Block*,
    5468              :                            Statement_inserter* inserter)
    5469              : {
    5470         2608 :   if (this->channel_->is_error_expression()
    5471         2608 :       || this->channel_->type()->is_error_type())
    5472              :     {
    5473            0 :       go_assert(saw_errors());
    5474            0 :       return Statement::make_error_statement(this->location());
    5475              :     }
    5476              : 
    5477         5216 :   Type* element_type = this->channel_->type()->channel_type()->element_type();
    5478         2608 :   if (!Type::are_identical(element_type, this->val_->type(),
    5479              :                            Type::COMPARE_ERRORS | Type::COMPARE_TAGS,
    5480              :                            NULL)
    5481           18 :       && this->val_->type()->interface_type() != NULL
    5482         2608 :       && !this->val_->is_multi_eval_safe())
    5483              :     {
    5484            0 :       Temporary_statement* temp =
    5485            0 :         Statement::make_temporary(NULL, this->val_, this->location());
    5486            0 :       inserter->insert(temp);
    5487            0 :       this->val_ = Expression::make_temporary_reference(temp,
    5488              :                                                         this->location());
    5489              :     }
    5490         2608 :   return this;
    5491              : }
    5492              : 
    5493              : // Add explicit type conversions.
    5494              : 
    5495              : void
    5496         2598 : Send_statement::do_add_conversions()
    5497              : {
    5498         5196 :   Type* lt = this->channel_->type()->channel_type()->element_type();
    5499         2598 :   Type* rt = this->val_->type();
    5500         2598 :   if (!Type::are_identical(lt, rt, 0, NULL)
    5501         2598 :       && lt->interface_type() != NULL)
    5502           97 :     this->val_ = Expression::make_cast(lt, this->val_, this->location());
    5503         2598 : }
    5504              : 
    5505              : // Convert a send statement to the backend representation.
    5506              : 
    5507              : Bstatement*
    5508         2597 : Send_statement::do_get_backend(Translate_context* context)
    5509              : {
    5510         2597 :   Gogo* gogo = context->gogo();
    5511         2597 :   Location loc = this->location();
    5512              : 
    5513         2597 :   Channel_type* channel_type = this->channel_->type()->channel_type();
    5514         2597 :   Type* element_type = channel_type->element_type();
    5515         2597 :   Expression* val = Expression::convert_for_assignment(gogo,
    5516              :                                                        element_type,
    5517              :                                                        this->val_, loc);
    5518              : 
    5519         2597 :   bool can_take_address;
    5520         2597 :   switch (element_type->base()->classification())
    5521              :     {
    5522              :     case Type::TYPE_BOOLEAN:
    5523              :     case Type::TYPE_INTEGER:
    5524              :     case Type::TYPE_FUNCTION:
    5525              :     case Type::TYPE_POINTER:
    5526              :     case Type::TYPE_MAP:
    5527              :     case Type::TYPE_CHANNEL:
    5528              :     case Type::TYPE_FLOAT:
    5529              :     case Type::TYPE_COMPLEX:
    5530              :     case Type::TYPE_STRING:
    5531              :     case Type::TYPE_INTERFACE:
    5532              :       can_take_address = false;
    5533              :       break;
    5534              : 
    5535              :     case Type::TYPE_STRUCT:
    5536              :       can_take_address = true;
    5537              :       break;
    5538              : 
    5539           15 :     case Type::TYPE_ARRAY:
    5540           15 :       can_take_address = !element_type->is_slice_type();
    5541           15 :       break;
    5542              : 
    5543            0 :     default:
    5544            0 :     case Type::TYPE_ERROR:
    5545            0 :     case Type::TYPE_VOID:
    5546            0 :     case Type::TYPE_SINK:
    5547            0 :     case Type::TYPE_NIL:
    5548            0 :     case Type::TYPE_NAMED:
    5549            0 :     case Type::TYPE_FORWARD:
    5550            0 :       go_assert(saw_errors());
    5551            0 :       return context->backend()->error_statement();
    5552              :     }
    5553              : 
    5554              :   // Only try to take the address of a variable.  We have already
    5555              :   // moved variables to the heap, so this should not cause that to
    5556              :   // happen unnecessarily.
    5557           15 :   if (can_take_address
    5558          320 :       && val->var_expression() == NULL
    5559         2294 :       && val->temporary_reference_expression() == NULL)
    5560              :     can_take_address = false;
    5561              : 
    5562         4818 :   Bstatement* btemp = NULL;
    5563         2279 :   if (can_take_address)
    5564              :     {
    5565              :       // The function doesn't change the value, so just take its
    5566              :       // address directly.
    5567           58 :       val = Expression::make_unary(OPERATOR_AND, val, loc);
    5568              :     }
    5569              :   else
    5570              :     {
    5571              :       // The value is not in a variable, or is small enough that it
    5572              :       // might be in a register, and taking the address would push it
    5573              :       // on the stack.  Copy it into a temporary variable to take the
    5574              :       // address.
    5575         2539 :       Temporary_statement* temp = Statement::make_temporary(element_type,
    5576              :                                                             val, loc);
    5577         2539 :       Expression* ref = Expression::make_temporary_reference(temp, loc);
    5578         2539 :       val = Expression::make_unary(OPERATOR_AND, ref, loc);
    5579         2539 :       btemp = temp->get_backend(context);
    5580              :     }
    5581              : 
    5582         2597 :   Expression* call = Runtime::make_call(gogo, Runtime::CHANSEND, loc, 2,
    5583         2597 :                                         this->channel_, val);
    5584         2597 :   call->determine_type_no_context(gogo);
    5585         2597 :   gogo->lower_expression(context->function(), NULL, &call);
    5586         2597 :   Bexpression* bcall = call->get_backend(context);
    5587         2597 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    5588         2597 :   Bstatement* s = context->backend()->expression_statement(bfunction, bcall);
    5589              : 
    5590         2597 :   if (btemp == NULL)
    5591              :     return s;
    5592              :   else
    5593         2539 :     return context->backend()->compound_statement(btemp, s);
    5594              : }
    5595              : 
    5596              : // Dump the AST representation for a send statement
    5597              : 
    5598              : void
    5599            0 : Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    5600              : {
    5601            0 :   ast_dump_context->print_indent();
    5602            0 :   ast_dump_context->dump_expression(this->channel_);
    5603            0 :   ast_dump_context->ostream() << " <- ";
    5604            0 :   ast_dump_context->dump_expression(this->val_);
    5605            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    5606            0 : }
    5607              : 
    5608              : // Make a send statement.
    5609              : 
    5610              : Send_statement*
    5611         2601 : Statement::make_send_statement(Expression* channel, Expression* val,
    5612              :                                Location location)
    5613              : {
    5614         2601 :   return new Send_statement(channel, val, location);
    5615              : }
    5616              : 
    5617              : // Class Select_clauses::Select_clause.
    5618              : 
    5619              : // Traversal.
    5620              : 
    5621              : int
    5622       164626 : Select_clauses::Select_clause::traverse(Traverse* traverse)
    5623              : {
    5624       164626 :   if (!this->is_lowered_
    5625       164626 :       && (traverse->traverse_mask()
    5626        39950 :           & (Traverse::traverse_types | Traverse::traverse_expressions)) != 0)
    5627              :     {
    5628        39950 :       if (this->channel_ != NULL)
    5629              :         {
    5630        32630 :           if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
    5631              :             return TRAVERSE_EXIT;
    5632              :         }
    5633        39950 :       if (this->val_ != NULL)
    5634              :         {
    5635        14765 :           if (Expression::traverse(&this->val_, traverse) == TRAVERSE_EXIT)
    5636              :             return TRAVERSE_EXIT;
    5637              :         }
    5638        39950 :       if (this->closed_ != NULL)
    5639              :         {
    5640           45 :           if (Expression::traverse(&this->closed_, traverse) == TRAVERSE_EXIT)
    5641              :             return TRAVERSE_EXIT;
    5642              :         }
    5643              :     }
    5644       164626 :   if (this->statements_ != NULL)
    5645              :     {
    5646       164626 :       if (this->statements_->traverse(traverse) == TRAVERSE_EXIT)
    5647              :         return TRAVERSE_EXIT;
    5648              :     }
    5649              :   return TRAVERSE_CONTINUE;
    5650              : }
    5651              : 
    5652              : // Lowering.  We call a function to register this clause, and arrange
    5653              : // to set any variables in any receive clause.
    5654              : 
    5655              : void
    5656         6746 : Select_clauses::Select_clause::lower(Gogo* gogo, Named_object* function,
    5657              :                                      Block* b, Temporary_statement* scases,
    5658              :                                      int index, Temporary_statement* recvok)
    5659              : {
    5660         6746 :   Location loc = this->location_;
    5661              : 
    5662         6746 :   this->set_case_index(index);
    5663              : 
    5664         6746 :   if (this->is_default_)
    5665              :     {
    5666          867 :       go_assert(this->channel_ == NULL && this->val_ == NULL);
    5667          867 :       this->is_lowered_ = true;
    5668          867 :       return;
    5669              :     }
    5670              : 
    5671         5879 :   Expression* scase = Expression::make_temporary_reference(scases, loc);
    5672         5879 :   Expression* index_expr = Expression::make_integer_sl(index, NULL, loc);
    5673         5879 :   scase = Expression::make_array_index(scase, index_expr, NULL, NULL, loc);
    5674              : 
    5675              :   // Evaluate the channel before the select statement.
    5676         5879 :   Temporary_statement* channel_temp = Statement::make_temporary(NULL,
    5677              :                                                                 this->channel_,
    5678              :                                                                 loc);
    5679         5879 :   b->add_statement(channel_temp);
    5680         5879 :   Expression* chanref = Expression::make_temporary_reference(channel_temp,
    5681              :                                                              loc);
    5682              : 
    5683         5879 :   if (this->is_send_)
    5684         1374 :     this->lower_send(gogo, b, scase, chanref);
    5685              :   else
    5686         4505 :     this->lower_recv(gogo, function, b, scase, chanref, recvok);
    5687              : 
    5688              :   // Now all references should be handled through the statements, not
    5689              :   // through here.
    5690         5879 :   this->is_lowered_ = true;
    5691         5879 :   this->val_ = NULL;
    5692              : }
    5693              : 
    5694              : // Lower a send clause in a select statement.
    5695              : 
    5696              : void
    5697         1374 : Select_clauses::Select_clause::lower_send(Gogo* gogo, Block* b,
    5698              :                                           Expression* scase,
    5699              :                                           Expression* chanref)
    5700              : {
    5701         1374 :   Location loc = this->location_;
    5702              : 
    5703         1374 :   Channel_type* ct = this->channel_->type()->channel_type();
    5704         1374 :   if (ct == NULL)
    5705            0 :     return;
    5706              : 
    5707         1374 :   Type* valtype = ct->element_type();
    5708              : 
    5709              :   // Note that copying the value to a temporary here means that we
    5710              :   // evaluate the send values in the required order.
    5711         1374 :   Temporary_statement* val = Statement::make_temporary(valtype, this->val_,
    5712              :                                                        loc);
    5713              :   // The value here escapes, because it might be sent on a channel.
    5714              :   // We record that via the Temporary_statement, so that the escape
    5715              :   // analysis pass can pick it up.  The gc compiler lowers select
    5716              :   // statements after escape analysis, so it doesn't have to worry
    5717              :   // about this.
    5718         1374 :   val->set_value_escapes();
    5719         1374 :   b->add_statement(val);
    5720              : 
    5721         1374 :   Expression* valref = Expression::make_temporary_reference(val, loc);
    5722         1374 :   Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
    5723         1374 :   Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
    5724         1374 :   valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
    5725              : 
    5726         1374 :   this->set_case(gogo, b, scase, chanref, valaddr);
    5727              : }
    5728              : 
    5729              : // Lower a receive clause in a select statement.
    5730              : 
    5731              : void
    5732         4505 : Select_clauses::Select_clause::lower_recv(Gogo* gogo, Named_object* function,
    5733              :                                           Block* b, Expression* scase,
    5734              :                                           Expression* chanref,
    5735              :                                           Temporary_statement* recvok)
    5736              : {
    5737         4505 :   Location loc = this->location_;
    5738              : 
    5739         4505 :   Channel_type* ct = this->channel_->type()->channel_type();
    5740         4505 :   if (ct == NULL)
    5741            0 :     return;
    5742              : 
    5743         4505 :   Type* valtype = ct->element_type();
    5744         4505 :   Temporary_statement* val = Statement::make_temporary(valtype, NULL, loc);
    5745         4505 :   b->add_statement(val);
    5746              : 
    5747         4505 :   Expression* valref = Expression::make_temporary_reference(val, loc);
    5748         4505 :   Expression* valaddr = Expression::make_unary(OPERATOR_AND, valref, loc);
    5749         4505 :   Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
    5750         4505 :   valaddr = Expression::make_cast(unsafe_pointer_type, valaddr, loc);
    5751              : 
    5752         4505 :   this->set_case(gogo, b, scase, chanref, valaddr);
    5753              : 
    5754              :   // If the block of statements is executed, arrange for the received
    5755              :   // value to move from VAL to the place where the statements expect
    5756              :   // it.
    5757              : 
    5758         4505 :   Block* init = NULL;
    5759              : 
    5760         4505 :   if (this->var_ != NULL)
    5761              :     {
    5762          460 :       go_assert(this->val_ == NULL);
    5763          460 :       valref = Expression::make_temporary_reference(val, loc);
    5764          460 :       this->var_->var_value()->set_init(valref);
    5765          460 :       this->var_->var_value()->clear_type_from_chan_element();
    5766              :     }
    5767         4045 :   else if (this->val_ != NULL && !this->val_->is_sink_expression())
    5768              :     {
    5769         1415 :       init = new Block(b, loc);
    5770         1415 :       valref = Expression::make_temporary_reference(val, loc);
    5771         1415 :       Statement* s = Statement::make_assignment(this->val_, valref, loc);
    5772         1415 :       s->determine_types(gogo);
    5773         1415 :       init->add_statement(s);
    5774              :     }
    5775              : 
    5776         4505 :   if (this->closedvar_ != NULL)
    5777              :     {
    5778           28 :       go_assert(this->closed_ == NULL);
    5779           28 :       Expression* cref = Expression::make_temporary_reference(recvok, loc);
    5780           28 :       this->closedvar_->var_value()->set_init(cref);
    5781              :     }
    5782         4477 :   else if (this->closed_ != NULL && !this->closed_->is_sink_expression())
    5783              :     {
    5784            7 :       if (init == NULL)
    5785            0 :         init = new Block(b, loc);
    5786            7 :       Expression* cref = Expression::make_temporary_reference(recvok, loc);
    5787            7 :       Statement* s = Statement::make_assignment(this->closed_, cref, loc);
    5788            7 :       s->determine_types(gogo);
    5789            7 :       init->add_statement(s);
    5790              :     }
    5791              : 
    5792         4505 :   if (init != NULL)
    5793              :     {
    5794         1415 :       gogo->lower_block(function, init);
    5795              : 
    5796         1415 :       if (this->statements_ != NULL)
    5797         1415 :         init->add_statement(Statement::make_block_statement(this->statements_,
    5798              :                                                             loc));
    5799         1415 :       this->statements_ = init;
    5800              :     }
    5801              : }
    5802              : 
    5803              : // Set the fields of an scase struct, an element in the array that we
    5804              : // pass to the runtime function selectgo.
    5805              : 
    5806              : void
    5807         5879 : Select_clauses::Select_clause::set_case(Gogo* gogo,
    5808              :                                         Block* b,
    5809              :                                         Expression* scase,
    5810              :                                         Expression* chanref,
    5811              :                                         Expression* elem)
    5812              : {
    5813         5879 :   Location loc = this->location_;
    5814         5879 :   Struct_type* scase_type = scase->type()->struct_type();
    5815              : 
    5816         5879 :   int field_index = 0;
    5817         5879 :   go_assert(scase_type->field(field_index)->is_field_name("c"));
    5818         5879 :   Expression* ref = Expression::make_field_reference(scase, field_index, loc);
    5819         5879 :   Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
    5820         5879 :   chanref = Expression::make_unsafe_cast(unsafe_pointer_type, chanref, loc);
    5821         5879 :   Statement* s = Statement::make_assignment(ref, chanref, loc);
    5822         5879 :   s->determine_types(gogo);
    5823         5879 :   b->add_statement(s);
    5824              : 
    5825         5879 :   if (elem != NULL)
    5826              :     {
    5827         5879 :       field_index = 1;
    5828         5879 :       go_assert(scase_type->field(field_index)->is_field_name("elem"));
    5829         5879 :       ref = Expression::make_field_reference(scase->copy(), field_index, loc);
    5830         5879 :       s = Statement::make_assignment(ref, elem, loc);
    5831         5879 :       s->determine_types(gogo);
    5832         5879 :       b->add_statement(s);
    5833              :     }
    5834         5879 : }
    5835              : 
    5836              : // Determine types.
    5837              : 
    5838              : void
    5839         8070 : Select_clauses::Select_clause::determine_types(Gogo* gogo)
    5840              : {
    5841         8070 :   if (this->channel_ != NULL)
    5842         6604 :     this->channel_->determine_type_no_context(gogo);
    5843         8070 :   if (this->val_ != NULL)
    5844         2953 :     this->val_->determine_type_no_context(gogo);
    5845         8070 :   if (this->closed_ != NULL)
    5846            9 :     this->closed_->determine_type_no_context(gogo);
    5847         8070 :   if (this->var_ != NULL && this->var_->is_variable())
    5848          538 :     this->var_->var_value()->determine_type(gogo);
    5849         8070 :   if (this->closedvar_ != NULL && this->closedvar_->is_variable())
    5850           41 :     this->closedvar_->var_value()->determine_type(gogo);
    5851         8070 :   if (this->statements_ != NULL)
    5852         8070 :     this->statements_->determine_types(gogo);
    5853         8070 : }
    5854              : 
    5855              : // Check types.
    5856              : 
    5857              : void
    5858         7990 : Select_clauses::Select_clause::check_types()
    5859              : {
    5860         7990 :   if (this->is_default_)
    5861              :     return;
    5862              : 
    5863         6526 :   Channel_type* ct = this->channel_->type()->channel_type();
    5864         6526 :   if (ct == NULL)
    5865              :     {
    5866            0 :       go_error_at(this->channel_->location(), "expected channel");
    5867            0 :       return;
    5868              :     }
    5869              : 
    5870         6526 :   if (this->is_send_ && !ct->may_send())
    5871            1 :     go_error_at(this->location(), "invalid send on receive-only channel");
    5872         6525 :   else if (!this->is_send_ && !ct->may_receive())
    5873            1 :     go_error_at(this->location(), "invalid receive on send-only channel");
    5874              : }
    5875              : 
    5876              : // Whether this clause may fall through to the statement which follows
    5877              : // the overall select statement.
    5878              : 
    5879              : bool
    5880          406 : Select_clauses::Select_clause::may_fall_through() const
    5881              : {
    5882          406 :   if (this->statements_ == NULL)
    5883              :     return true;
    5884          406 :   return this->statements_->may_fall_through();
    5885              : }
    5886              : 
    5887              : // Return the backend representation for the statements to execute.
    5888              : 
    5889              : Bstatement*
    5890         6734 : Select_clauses::Select_clause::get_statements_backend(
    5891              :     Translate_context* context)
    5892              : {
    5893         6734 :   if (this->statements_ == NULL)
    5894              :     return NULL;
    5895         6734 :   Bblock* bblock = this->statements_->get_backend(context);
    5896         6734 :   return context->backend()->block_statement(bblock);
    5897              : }
    5898              : 
    5899              : // Dump the AST representation for a select case clause
    5900              : 
    5901              : void
    5902            0 : Select_clauses::Select_clause::dump_clause(
    5903              :     Ast_dump_context* ast_dump_context) const
    5904              : {
    5905            0 :   ast_dump_context->print_indent();
    5906            0 :   if (this->is_default_)
    5907              :     {
    5908            0 :       ast_dump_context->ostream() << "default:";
    5909              :     }
    5910              :   else
    5911              :     {
    5912            0 :       ast_dump_context->ostream() << "case "  ;
    5913            0 :       if (this->is_send_)
    5914              :         {
    5915            0 :           ast_dump_context->dump_expression(this->channel_);
    5916            0 :           ast_dump_context->ostream() << " <- " ;
    5917            0 :           if (this->val_ != NULL)
    5918            0 :             ast_dump_context->dump_expression(this->val_);
    5919              :         }
    5920              :       else
    5921              :         {
    5922            0 :           if (this->val_ != NULL)
    5923            0 :             ast_dump_context->dump_expression(this->val_);
    5924            0 :           if (this->closed_ != NULL)
    5925              :             {
    5926              :               // FIXME: can val_ == NULL and closed_ ! = NULL?
    5927            0 :               ast_dump_context->ostream() << " , " ;
    5928            0 :               ast_dump_context->dump_expression(this->closed_);
    5929              :             }
    5930            0 :           if (this->closedvar_ != NULL || this->var_ != NULL)
    5931            0 :             ast_dump_context->ostream() << " := " ;
    5932              : 
    5933            0 :           ast_dump_context->ostream() << " <- " ;
    5934            0 :           ast_dump_context->dump_expression(this->channel_);
    5935              :         }
    5936            0 :       ast_dump_context->ostream() << ":" ;
    5937              :     }
    5938            0 :   ast_dump_context->dump_block(this->statements_);
    5939            0 : }
    5940              : 
    5941              : // Class Select_clauses.
    5942              : 
    5943              : // Whether there is a default case.
    5944              : 
    5945              : bool
    5946         2656 : Select_clauses::has_default() const
    5947              : {
    5948         7202 :   for (Clauses::const_iterator p = this->clauses_.begin();
    5949         7202 :        p != this->clauses_.end();
    5950         4546 :        ++p)
    5951         6010 :     if (p->is_default())
    5952         2656 :       return true;
    5953              :   return false;
    5954              : }
    5955              : 
    5956              : // Traversal.
    5957              : 
    5958              : int
    5959        49708 : Select_clauses::traverse(Traverse* traverse)
    5960              : {
    5961       214334 :   for (Clauses::iterator p = this->clauses_.begin();
    5962       214334 :        p != this->clauses_.end();
    5963       164626 :        ++p)
    5964              :     {
    5965       164626 :       if (p->traverse(traverse) == TRAVERSE_EXIT)
    5966        49708 :         return TRAVERSE_EXIT;
    5967              :     }
    5968              :   return TRAVERSE_CONTINUE;
    5969              : }
    5970              : 
    5971              : // Lowering.  Here we pull out the channel and the send values, to
    5972              : // enforce the order of evaluation.  We also add explicit send and
    5973              : // receive statements to the clauses.  This builds the entries in the
    5974              : // local array of scase values.  It sets *P_SEND_COUNT and
    5975              : // *P_RECV_COUNT.
    5976              : 
    5977              : void
    5978         1951 : Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
    5979              :                       Temporary_statement* scases, Temporary_statement* recvok,
    5980              :                       int *p_send_count, int *p_recv_count)
    5981              : {
    5982         1951 :   int send_count = 0;
    5983         1951 :   int recv_count = 0;
    5984         1951 :   bool has_default = false;
    5985         8697 :   for (Clauses::iterator p = this->clauses_.begin();
    5986         8697 :        p != this->clauses_.end();
    5987         6746 :        ++p)
    5988              :     {
    5989         6746 :       if (p->is_default())
    5990              :         has_default = true;
    5991         5879 :       else if (p->is_send())
    5992         1374 :         ++send_count;
    5993              :       else
    5994         4505 :         ++recv_count;
    5995              :     }
    5996              : 
    5997         1951 :   *p_send_count = send_count;
    5998         1951 :   *p_recv_count = recv_count;
    5999              : 
    6000         1951 :   int send_index = 0;
    6001         1951 :   int recv_index = send_count;
    6002         8697 :   for (Clauses::iterator p = this->clauses_.begin();
    6003         8697 :        p != this->clauses_.end();
    6004         6746 :        ++p)
    6005              :     {
    6006         6746 :       int index;
    6007         6746 :       if (p->is_default())
    6008              :         index = -1;
    6009         5879 :       else if (p->is_send())
    6010              :         {
    6011         1374 :           index = send_index;
    6012         1374 :           ++send_index;
    6013              :         }
    6014              :       else
    6015              :         {
    6016         4505 :           index = recv_index;
    6017         4505 :           ++recv_index;
    6018              :         }
    6019              : 
    6020         6746 :       p->lower(gogo, function, b, scases, index, recvok);
    6021              :     }
    6022              : 
    6023         1951 :   go_assert(send_index == send_count);
    6024         1951 :   go_assert(recv_index == send_count + recv_count);
    6025         3035 :   go_assert(static_cast<size_t>(recv_index + (has_default ? 1 : 0))
    6026              :             == this->size());
    6027         1951 : }
    6028              : 
    6029              : // Determine types.
    6030              : 
    6031              : void
    6032         2695 : Select_clauses::determine_types(Gogo* gogo)
    6033              : {
    6034        10765 :   for (Clauses::iterator p = this->clauses_.begin();
    6035        10765 :        p != this->clauses_.end();
    6036         8070 :        ++p)
    6037         8070 :     p->determine_types(gogo);
    6038         2695 : }
    6039              : 
    6040              : // Check types.
    6041              : 
    6042              : void
    6043         2656 : Select_clauses::check_types()
    6044              : {
    6045        10646 :   for (Clauses::iterator p = this->clauses_.begin();
    6046        10646 :        p != this->clauses_.end();
    6047         7990 :        ++p)
    6048         7990 :     p->check_types();
    6049         2656 : }
    6050              : 
    6051              : // Return whether these select clauses fall through to the statement
    6052              : // following the overall select statement.
    6053              : 
    6054              : bool
    6055          194 : Select_clauses::may_fall_through() const
    6056              : {
    6057          588 :   for (Clauses::const_iterator p = this->clauses_.begin();
    6058          588 :        p != this->clauses_.end();
    6059          394 :        ++p)
    6060          406 :     if (p->may_fall_through())
    6061          194 :       return true;
    6062              :   return false;
    6063              : }
    6064              : 
    6065              : // Convert to the backend representation.  Assemble the clauses and
    6066              : // build a switch statement on the index value returned by the call to
    6067              : // selectgo.
    6068              : 
    6069              : Bstatement*
    6070         1945 : Select_clauses::get_backend(Translate_context* context,
    6071              :                             Temporary_statement* index,
    6072              :                             Unnamed_label *break_label,
    6073              :                             Location location)
    6074              : {
    6075         1945 :   size_t count = this->clauses_.size();
    6076         1945 :   std::vector<std::vector<Bexpression*> > cases(count + 1);
    6077         1945 :   std::vector<Bstatement*> clauses(count + 1);
    6078              : 
    6079         1945 :   Type* int_type = Type::lookup_integer_type("int");
    6080              : 
    6081         1945 :   int i = 0;
    6082         1945 :   for (Clauses::iterator p = this->clauses_.begin();
    6083         8679 :        p != this->clauses_.end();
    6084         6734 :        ++p, ++i)
    6085              :     {
    6086         6734 :       Expression* index_expr = Expression::make_integer_sl(p->case_index(),
    6087              :                                                            int_type,
    6088              :                                                            location);
    6089         6734 :       cases[i].push_back(index_expr->get_backend(context));
    6090              : 
    6091         6734 :       Bstatement* s = p->get_statements_backend(context);
    6092         6734 :       Location gloc = (p->statements() == NULL
    6093         6734 :                        ? p->location()
    6094         6734 :                        : p->statements()->end_location());
    6095         6734 :       Bstatement* g = break_label->get_goto(context, gloc);
    6096              : 
    6097         6734 :       if (s == NULL)
    6098            0 :         clauses[i] = g;
    6099              :       else
    6100         6734 :         clauses[i] = context->backend()->compound_statement(s, g);
    6101              :     }
    6102              : 
    6103         1945 :   Expression* ref = Expression::make_temporary_reference(index, location);
    6104         1945 :   Bexpression* bindex = ref->get_backend(context);
    6105              : 
    6106         1945 :   Bfunction* bfunction = context->function()->func_value()->get_decl();
    6107              : 
    6108         1945 :   if (count == 0)
    6109            0 :     return context->backend()->expression_statement(bfunction, bindex);
    6110              : 
    6111         1945 :   Gogo* gogo = context->gogo();
    6112         1945 :   Expression* crash = Runtime::make_call(gogo, Runtime::UNREACHABLE,
    6113              :                                          location, 0);
    6114         1945 :   crash->determine_type_no_context(gogo);
    6115         1945 :   Bexpression* bcrash = crash->get_backend(context);
    6116         1945 :   clauses[count] = context->backend()->expression_statement(bfunction, bcrash);
    6117              : 
    6118         1945 :   std::vector<Bstatement*> statements;
    6119         1945 :   statements.reserve(2);
    6120              : 
    6121         1945 :   Bstatement* switch_stmt = context->backend()->switch_statement(bfunction,
    6122              :                                                                  bindex,
    6123              :                                                                  cases,
    6124              :                                                                  clauses,
    6125         1945 :                                                                  location);
    6126         1945 :   statements.push_back(switch_stmt);
    6127              : 
    6128         1945 :   Bstatement* ldef = break_label->get_definition(context);
    6129         1945 :   statements.push_back(ldef);
    6130              : 
    6131         1945 :   return context->backend()->statement_list(statements);
    6132         3890 : }
    6133              : 
    6134              : // Dump the AST representation for select clauses.
    6135              : 
    6136              : void
    6137            0 : Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
    6138              : {
    6139            0 :   for (Clauses::const_iterator p = this->clauses_.begin();
    6140            0 :        p != this->clauses_.end();
    6141            0 :        ++p)
    6142            0 :     p->dump_clause(ast_dump_context);
    6143            0 : }
    6144              : 
    6145              : // Class Select_statement.
    6146              : 
    6147              : // Return the break label for this switch statement, creating it if
    6148              : // necessary.
    6149              : 
    6150              : Unnamed_label*
    6151         2671 : Select_statement::break_label()
    6152              : {
    6153         2671 :   if (this->break_label_ == NULL)
    6154         2607 :     this->break_label_ = new Unnamed_label(this->location());
    6155         2671 :   return this->break_label_;
    6156              : }
    6157              : 
    6158              : // Lower a select statement.  This will return a block containing this
    6159              : // select statement.  The block will implement the order of evaluation
    6160              : // rules, include the send and receive statements as explicit
    6161              : // statements in the clauses, and call the runtime selectgo function.
    6162              : 
    6163              : Statement*
    6164         5033 : Select_statement::do_lower(Gogo* gogo, Named_object* function,
    6165              :                            Block* enclosing, Statement_inserter*)
    6166              : {
    6167         5033 :   if (this->is_lowered_)
    6168         2377 :     return this;
    6169              : 
    6170         2656 :   Location loc = this->location();
    6171              : 
    6172         2656 :   Block* b = new Block(enclosing, loc);
    6173              : 
    6174         2656 :   int ncases = this->clauses_->size();
    6175         2656 :   bool has_default = this->clauses_->has_default();
    6176              : 
    6177              :   // Zero-case select.  Just block the execution.
    6178         2656 :   if (ncases == 0)
    6179              :     {
    6180           45 :       Expression* call = Runtime::make_call(gogo, Runtime::BLOCK, loc, 0);
    6181           45 :       Statement *s = Statement::make_statement(call, false);
    6182           45 :       s->determine_types(gogo);
    6183           45 :       b->add_statement(s);
    6184           45 :       this->is_lowered_ = true;
    6185           45 :       return Statement::make_block_statement(b, loc);
    6186              :     }
    6187              : 
    6188              :   // One-case select.  It is mostly just to run the case.
    6189         2611 :   if (ncases == 1)
    6190           76 :     return this->lower_one_case(gogo, b);
    6191              : 
    6192              :   // Two-case select with one default case.  It is a non-blocking
    6193              :   // send/receive.
    6194         2535 :   if (ncases == 2 && has_default)
    6195          584 :     return this->lower_two_case(gogo, b);
    6196              : 
    6197              :   // We don't allocate an entry in scases for the default case.
    6198         1951 :   if (has_default)
    6199          867 :     --ncases;
    6200              : 
    6201         1951 :   Type* scase_type = Channel_type::select_case_type();
    6202         1951 :   Expression* ncases_expr =
    6203         1951 :     Expression::make_integer_ul(ncases, NULL,
    6204              :                                 Linemap::predeclared_location());
    6205         1951 :   Array_type* scases_type = Type::make_array_type(scase_type, ncases_expr);
    6206         1951 :   scases_type->set_is_array_incomparable();
    6207              : 
    6208         1951 :   Temporary_statement* scases = Statement::make_temporary(scases_type, NULL,
    6209              :                                                           loc);
    6210         1951 :   b->add_statement(scases);
    6211              : 
    6212         1951 :   Expression* ncases2_expr =
    6213         1951 :     Expression::make_integer_ul(ncases * 2, NULL,
    6214              :                                 Linemap::predeclared_location());
    6215         1951 :   Type* uint16_type = Type::lookup_integer_type("uint16");
    6216         1951 :   Array_type* order_type = Type::make_array_type(uint16_type, ncases2_expr);
    6217         1951 :   order_type->set_is_array_incomparable();
    6218              : 
    6219         1951 :   Temporary_statement* order = Statement::make_temporary(order_type, NULL,
    6220              :                                                          loc);
    6221         1951 :   b->add_statement(order);
    6222              : 
    6223         1951 :   Type* int_type = Type::lookup_integer_type("int");
    6224         1951 :   this->index_ = Statement::make_temporary(int_type, NULL, loc);
    6225         1951 :   b->add_statement(this->index_);
    6226              : 
    6227         1951 :   Type* bool_type = Type::lookup_bool_type();
    6228         1951 :   Temporary_statement* recvok = Statement::make_temporary(bool_type, NULL,
    6229              :                                                           loc);
    6230         1951 :   b->add_statement(recvok);
    6231              : 
    6232              :   // Initialize the scases array.
    6233         1951 :   int send_count;
    6234         1951 :   int recv_count;
    6235         1951 :   this->clauses_->lower(gogo, function, b, scases, recvok, &send_count,
    6236              :                         &recv_count);
    6237              : 
    6238              :   // Build the call to selectgo.  Later, in do_get_backend, we will
    6239              :   // build a switch on the result that branches to the various cases.
    6240              : 
    6241         1951 :   Expression* scases_ref = Expression::make_temporary_reference(scases, loc);
    6242         1951 :   scases_ref = Expression::make_unary(OPERATOR_AND, scases_ref, loc);
    6243         1951 :   Type* unsafe_pointer_type = Type::make_pointer_type(Type::make_void_type());
    6244         1951 :   scases_ref = Expression::make_cast(unsafe_pointer_type, scases_ref, loc);
    6245              : 
    6246         1951 :   Expression* order_ref = Expression::make_temporary_reference(order, loc);
    6247         1951 :   order_ref = Expression::make_unary(OPERATOR_AND, order_ref, loc);
    6248         1951 :   order_ref = Expression::make_cast(unsafe_pointer_type, order_ref, loc);
    6249              : 
    6250         1951 :   Expression* send_count_expr = Expression::make_integer_sl(send_count,
    6251              :                                                             int_type,
    6252              :                                                             loc);
    6253         1951 :   Expression* recv_count_expr = Expression::make_integer_sl(recv_count,
    6254              :                                                             int_type,
    6255              :                                                             loc);
    6256         1951 :   Expression* block_expr = Expression::make_boolean(!has_default, loc);
    6257              : 
    6258         1951 :   Call_expression* call = Runtime::make_call(gogo, Runtime::SELECTGO, loc, 5,
    6259              :                                              scases_ref, order_ref,
    6260              :                                              send_count_expr, recv_count_expr,
    6261              :                                              block_expr);
    6262              : 
    6263         1951 :   Expression* result = Expression::make_call_result(call, 0);
    6264         1951 :   Expression* ref = Expression::make_temporary_reference(this->index_, loc);
    6265         1951 :   Statement* s = Statement::make_assignment(ref, result, loc);
    6266         1951 :   s->determine_types(gogo);
    6267         1951 :   b->add_statement(s);
    6268              : 
    6269         1951 :   result = Expression::make_call_result(call, 1);
    6270         1951 :   ref = Expression::make_temporary_reference(recvok, loc);
    6271         1951 :   s = Statement::make_assignment(ref, result, loc);
    6272         1951 :   s->determine_types(gogo);
    6273         1951 :   b->add_statement(s);
    6274              : 
    6275         1951 :   this->is_lowered_ = true;
    6276         1951 :   b->add_statement(this);
    6277              : 
    6278         1951 :   return Statement::make_block_statement(b, loc);
    6279              : }
    6280              : 
    6281              : // Lower a one-case select statement.
    6282              : 
    6283              : Statement*
    6284           76 : Select_statement::lower_one_case(Gogo* gogo, Block* b)
    6285              : {
    6286           76 :   Select_clauses::Select_clause& scase = this->clauses_->at(0);
    6287           76 :   Location loc = this->location();
    6288           76 :   Expression* chan = scase.channel();
    6289           76 :   if (chan != NULL)
    6290              :     {
    6291              :       // Lower this to
    6292              :       //   if chan == nil { block() }; send/recv; body
    6293           63 :       Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
    6294           63 :       b->add_statement(chantmp);
    6295           63 :       Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
    6296              : 
    6297           63 :       Expression* nil = Expression::make_nil(loc);
    6298           63 :       Expression* cond = Expression::make_binary(OPERATOR_EQEQ, chanref, nil, loc);
    6299           63 :       Block* bnil = new Block(b, loc);
    6300           63 :       Expression* call = Runtime::make_call(gogo, Runtime::BLOCK, loc, 0);
    6301           63 :       Statement* s = Statement::make_statement(call, false);
    6302           63 :       s->determine_types(gogo);
    6303           63 :       bnil->add_statement(s);
    6304           63 :       Statement* ifs = Statement::make_if_statement(cond, bnil, NULL, loc);
    6305           63 :       ifs->determine_types(gogo);
    6306           63 :       b->add_statement(ifs);
    6307              : 
    6308           63 :       chanref = chanref->copy();
    6309           63 :       Location cloc = scase.location();
    6310           63 :       if (scase.is_send())
    6311              :         {
    6312            7 :           s = Statement::make_send_statement(chanref, scase.val(), cloc);
    6313            7 :           s->determine_types(gogo);
    6314            7 :           b->add_statement(s);
    6315              :         }
    6316              :       else
    6317              :         {
    6318           56 :           if (scase.closed() == NULL && scase.closedvar() == NULL)
    6319              :             {
    6320              :               // Simple receive.
    6321           51 :               Expression* recv = Expression::make_receive(chanref, cloc);
    6322           51 :               if (scase.val() != NULL)
    6323            9 :                 s = Statement::make_assignment(scase.val(), recv, cloc);
    6324           42 :               else if (scase.var() != NULL)
    6325              :                 {
    6326            7 :                   Temporary_statement *ts =
    6327            7 :                     Statement::make_temporary(NULL, recv, cloc);
    6328            7 :                   Expression* ref =
    6329            7 :                     Expression::make_temporary_reference(ts, cloc);
    6330            7 :                   s = ts;
    6331            7 :                   scase.var()->var_value()->set_init(ref);
    6332            7 :                   scase.var()->var_value()->clear_type_from_chan_element();
    6333              :                 }
    6334              :               else
    6335           35 :                 s = Statement::make_statement(recv, false);
    6336           51 :               s->determine_types(gogo);
    6337           51 :               b->add_statement(s);
    6338              :             }
    6339              :           else
    6340              :             {
    6341              :               // Tuple receive.
    6342            5 :               Expression* lhs;
    6343            5 :               if (scase.val() != NULL)
    6344              :                 lhs = scase.val();
    6345              :               else
    6346              :                 {
    6347            8 :                   Type* valtype = chan->type()->channel_type()->element_type();
    6348            4 :                   Temporary_statement *ts =
    6349            4 :                     Statement::make_temporary(valtype, NULL, cloc);
    6350            4 :                   lhs = Expression::make_temporary_reference(ts, cloc);
    6351            4 :                   b->add_statement(ts);
    6352              :                 }
    6353              : 
    6354            5 :               Expression* lhs2;
    6355            5 :               if (scase.closed() != NULL)
    6356              :                 lhs2 = scase.closed();
    6357              :               else
    6358              :                 {
    6359            4 :                   Type* booltype = Type::make_boolean_type();
    6360            4 :                   Temporary_statement *ts =
    6361            4 :                     Statement::make_temporary(booltype, NULL, cloc);
    6362            4 :                   lhs2 = Expression::make_temporary_reference(ts, cloc);
    6363            4 :                   b->add_statement(ts);
    6364              :                 }
    6365              : 
    6366            5 :               s = Statement::make_tuple_receive_assignment(lhs, lhs2, chanref, cloc);
    6367            5 :               s->determine_types(gogo);
    6368            5 :               b->add_statement(s);
    6369              : 
    6370            5 :               if (scase.var() != NULL)
    6371              :                 {
    6372            3 :                   scase.var()->var_value()->set_init(lhs->copy());
    6373            3 :                   scase.var()->var_value()->clear_type_from_chan_element();
    6374              :                 }
    6375              : 
    6376            5 :               if (scase.closedvar() != NULL)
    6377            4 :                 scase.closedvar()->var_value()->set_init(lhs2->copy());
    6378              :             }
    6379              :         }
    6380              :     }
    6381              : 
    6382           76 :   Statement* bs =
    6383           76 :     Statement::make_block_statement(scase.statements(), scase.location());
    6384           76 :   b->add_statement(bs);
    6385              : 
    6386           76 :   Statement* label =
    6387           76 :     Statement::make_unnamed_label_statement(this->break_label());
    6388           76 :   b->add_statement(label);
    6389              : 
    6390           76 :   this->is_lowered_ = true;
    6391           76 :   return Statement::make_block_statement(b, loc);
    6392              : }
    6393              : 
    6394              : // Lower a two-case select statement with one default case.
    6395              : 
    6396              : Statement*
    6397          584 : Select_statement::lower_two_case(Gogo* gogo, Block* b)
    6398              : {
    6399          584 :   Select_clauses::Select_clause& chancase =
    6400          584 :     (this->clauses_->at(0).is_default()
    6401          584 :      ? this->clauses_->at(1)
    6402          495 :      : this->clauses_->at(0));
    6403          584 :   Select_clauses::Select_clause& defcase =
    6404          584 :     (this->clauses_->at(0).is_default()
    6405          584 :      ? this->clauses_->at(0)
    6406          495 :      : this->clauses_->at(1));
    6407          584 :   Location loc = this->location();
    6408          584 :   Expression* chan = chancase.channel();
    6409         1168 :   Type* valtype = chan->type()->channel_type()->element_type();
    6410              : 
    6411          584 :   Temporary_statement* chantmp = Statement::make_temporary(NULL, chan, loc);
    6412          584 :   b->add_statement(chantmp);
    6413          584 :   Expression* chanref = Expression::make_temporary_reference(chantmp, loc);
    6414              : 
    6415          584 :   Block* bchan;
    6416          584 :   Expression* cond;
    6417          584 :   if (chancase.is_send())
    6418              :     {
    6419              :       // if selectnbsend(chan, &val) { body } else { default body }
    6420              : 
    6421           99 :       Temporary_statement* ts =
    6422           99 :         Statement::make_temporary(valtype, chancase.val(), loc);
    6423              :       // Tell the escape analysis that the value escapes, as it may be sent
    6424              :       // to a channel.
    6425           99 :       ts->set_value_escapes();
    6426           99 :       b->add_statement(ts);
    6427              : 
    6428           99 :       Expression* ref = Expression::make_temporary_reference(ts, loc);
    6429           99 :       Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
    6430           99 :       cond = Runtime::make_call(gogo, Runtime::SELECTNBSEND, loc, 2,
    6431              :                                 chanref, addr);
    6432           99 :       bchan = chancase.statements();
    6433              :     }
    6434              :   else
    6435              :     {
    6436          485 :       Temporary_statement* ts = Statement::make_temporary(valtype, NULL, loc);
    6437          485 :       b->add_statement(ts);
    6438              : 
    6439          485 :       Expression* ref = Expression::make_temporary_reference(ts, loc);
    6440          485 :       Expression* addr = Expression::make_unary(OPERATOR_AND, ref, loc);
    6441              : 
    6442              :       // selected, ok = selectnbrecv(&lhs, chan)
    6443          485 :       Call_expression* call = Runtime::make_call(gogo, Runtime::SELECTNBRECV,
    6444              :                                                  loc, 2, addr, chanref);
    6445              : 
    6446          485 :       Temporary_statement* selected_temp =
    6447          485 :         Statement::make_temporary(Type::make_boolean_type(),
    6448              :                                   Expression::make_call_result(call, 0),
    6449              :                                   loc);
    6450          485 :       selected_temp->determine_types(gogo);
    6451          485 :       b->add_statement(selected_temp);
    6452              : 
    6453          485 :       Temporary_statement* ok_temp =
    6454          485 :         Statement::make_temporary(Type::make_boolean_type(),
    6455              :                                   Expression::make_call_result(call, 1),
    6456              :                                   loc);
    6457          485 :       ok_temp->determine_types(gogo);
    6458          485 :       b->add_statement(ok_temp);
    6459              : 
    6460          485 :       cond = Expression::make_temporary_reference(selected_temp, loc);
    6461              : 
    6462          485 :       Location cloc = chancase.location();
    6463          485 :       bchan = new Block(b, loc);
    6464          485 :       if (chancase.val() != NULL && !chancase.val()->is_sink_expression())
    6465              :         {
    6466           43 :           Statement* as = Statement::make_assignment(chancase.val(),
    6467              :                                                      ref->copy(),
    6468              :                                                      cloc);
    6469           43 :           as->determine_types(gogo);
    6470           43 :           bchan->add_statement(as);
    6471              :         }
    6472          442 :       else if (chancase.var() != NULL)
    6473              :         {
    6474           54 :           chancase.var()->var_value()->set_init(ref->copy());
    6475           54 :           chancase.var()->var_value()->clear_type_from_chan_element();
    6476              :         }
    6477              : 
    6478          485 :       if (chancase.closed() != NULL && !chancase.closed()->is_sink_expression())
    6479              :         {
    6480            1 :           Expression* okref = Expression::make_temporary_reference(ok_temp,
    6481              :                                                                    cloc);
    6482            1 :           Statement* as = Statement::make_assignment(chancase.closed(),
    6483              :                                                      okref, cloc);
    6484            1 :           as->determine_types(gogo);
    6485            1 :           bchan->add_statement(as);
    6486              :         }
    6487          484 :       else if (chancase.closedvar() != NULL)
    6488              :         {
    6489            9 :           Expression* okref = Expression::make_temporary_reference(ok_temp,
    6490              :                                                                    cloc);
    6491            9 :           chancase.closedvar()->var_value()->set_init(okref);
    6492              :         }
    6493              : 
    6494          485 :       Statement* bs = Statement::make_block_statement(chancase.statements(),
    6495              :                                                       cloc);
    6496          485 :       bchan->add_statement(bs);
    6497              :     }
    6498              : 
    6499          584 :   Statement* ifs =
    6500          584 :     Statement::make_if_statement(cond, bchan, defcase.statements(), loc);
    6501          584 :   ifs->determine_types(gogo);
    6502          584 :   b->add_statement(ifs);
    6503              : 
    6504          584 :   Statement* label =
    6505          584 :     Statement::make_unnamed_label_statement(this->break_label());
    6506          584 :   b->add_statement(label);
    6507              : 
    6508          584 :   this->is_lowered_ = true;
    6509          584 :   return Statement::make_block_statement(b, loc);
    6510              : }
    6511              : 
    6512              : // Whether the select statement itself may fall through to the following
    6513              : // statement.
    6514              : 
    6515              : bool
    6516          214 : Select_statement::do_may_fall_through() const
    6517              : {
    6518              :   // A select statement is terminating if no break statement
    6519              :   // refers to it and all of its clauses are terminating.
    6520          214 :   if (this->break_label_ != NULL)
    6521              :     return true;
    6522          194 :   return this->clauses_->may_fall_through();
    6523              : }
    6524              : 
    6525              : // Return the backend representation for a select statement.
    6526              : 
    6527              : Bstatement*
    6528         1945 : Select_statement::do_get_backend(Translate_context* context)
    6529              : {
    6530         1945 :   return this->clauses_->get_backend(context, this->index_,
    6531         1945 :                                      this->break_label(), this->location());
    6532              : }
    6533              : 
    6534              : // Dump the AST representation for a select statement.
    6535              : 
    6536              : void
    6537            0 : Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    6538              : {
    6539            0 :   ast_dump_context->print_indent();
    6540            0 :   ast_dump_context->ostream() << "select";
    6541            0 :   if (ast_dump_context->dump_subblocks())
    6542              :     {
    6543            0 :       ast_dump_context->ostream() << " {" << dsuffix(location()) << std::endl;
    6544            0 :       this->clauses_->dump_clauses(ast_dump_context);
    6545            0 :       ast_dump_context->print_indent();
    6546            0 :       ast_dump_context->ostream() << "}";
    6547              :     }
    6548            0 :   ast_dump_context->ostream() << std::endl;
    6549            0 : }
    6550              : 
    6551              : // Make a select statement.
    6552              : 
    6553              : Select_statement*
    6554         2656 : Statement::make_select_statement(Location location)
    6555              : {
    6556         2656 :   return new Select_statement(location);
    6557              : }
    6558              : 
    6559              : // Class For_statement.
    6560              : 
    6561              : // Traversal.
    6562              : 
    6563              : int
    6564       174482 : For_statement::do_traverse(Traverse* traverse)
    6565              : {
    6566       174482 :   if (this->init_ != NULL)
    6567              :     {
    6568        34013 :       if (this->init_->traverse(traverse) == TRAVERSE_EXIT)
    6569              :         return TRAVERSE_EXIT;
    6570              :     }
    6571       174482 :   if (this->cond_ != NULL)
    6572              :     {
    6573       155516 :       if (this->traverse_expression(traverse, &this->cond_) == TRAVERSE_EXIT)
    6574              :         return TRAVERSE_EXIT;
    6575              :     }
    6576       174482 :   if (this->post_ != NULL)
    6577              :     {
    6578       123247 :       if (this->post_->traverse(traverse) == TRAVERSE_EXIT)
    6579              :         return TRAVERSE_EXIT;
    6580              :     }
    6581       174482 :   return this->statements_->traverse(traverse);
    6582              : }
    6583              : 
    6584              : void
    6585        62188 : For_statement::do_determine_types(Gogo* gogo)
    6586              : {
    6587        62188 :   if (this->init_ != NULL)
    6588        34013 :     this->init_->determine_types(gogo);
    6589        62188 :   if (this->cond_ != NULL)
    6590        58314 :     this->cond_->determine_type_no_context(gogo);
    6591        62188 :   if (this->post_ != NULL)
    6592        51860 :     this->post_->determine_types(gogo);
    6593        62188 :   this->statements_->determine_types(gogo);
    6594        62188 : }
    6595              : 
    6596              : void
    6597        28074 : For_statement::do_check_types(Gogo*)
    6598              : {
    6599        28074 :   if (this->cond_ != NULL)
    6600              :     {
    6601        24301 :       Type* type = this->cond_->type();
    6602        24301 :       if (type->is_error())
    6603            1 :         this->set_is_error();
    6604        24300 :       else if (!type->is_boolean_type())
    6605              :         {
    6606            1 :           go_error_at(this->cond_->location(), "expected boolean expression");
    6607            1 :           this->set_is_error();
    6608              :         }
    6609              :     }
    6610        28074 : }
    6611              : 
    6612              : // Lower a For_statement into if statements and gotos.  Getting rid of
    6613              : // complex statements make it easier to handle garbage collection.
    6614              : 
    6615              : Statement*
    6616        62186 : For_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
    6617              :                         Statement_inserter*)
    6618              : {
    6619        62186 :   Location loc = this->location();
    6620              : 
    6621        62186 :   if (this->classification() == STATEMENT_ERROR)
    6622            0 :     return Statement::make_error_statement(loc);
    6623              : 
    6624        62186 :   Statement* s;
    6625        62186 :   Block* b = new Block(enclosing, this->location());
    6626        62186 :   if (this->init_ != NULL)
    6627              :     {
    6628        68026 :       s = Statement::make_block_statement(this->init_,
    6629        34013 :                                           this->init_->start_location());
    6630        34013 :       b->add_statement(s);
    6631              :     }
    6632              : 
    6633        62186 :   Unnamed_label* entry = NULL;
    6634        62186 :   if (this->cond_ != NULL)
    6635              :     {
    6636        58312 :       entry = new Unnamed_label(this->location());
    6637        58312 :       b->add_statement(Statement::make_goto_unnamed_statement(entry, loc));
    6638              :     }
    6639              : 
    6640        62186 :   Unnamed_label* top = new Unnamed_label(this->location());
    6641        62186 :   top->set_derived_from(this);
    6642        62186 :   b->add_statement(Statement::make_unnamed_label_statement(top));
    6643              : 
    6644       124372 :   s = Statement::make_block_statement(this->statements_,
    6645        62186 :                                       this->statements_->start_location());
    6646        62186 :   b->add_statement(s);
    6647              : 
    6648        62186 :   Location end_loc = this->statements_->end_location();
    6649              : 
    6650        62186 :   Unnamed_label* cont = this->continue_label_;
    6651        62186 :   if (cont != NULL)
    6652         6370 :     b->add_statement(Statement::make_unnamed_label_statement(cont));
    6653              : 
    6654        62186 :   if (this->post_ != NULL)
    6655              :     {
    6656       103718 :       s = Statement::make_block_statement(this->post_,
    6657        51859 :                                           this->post_->start_location());
    6658        51859 :       b->add_statement(s);
    6659        51859 :       end_loc = this->post_->end_location();
    6660              :     }
    6661              : 
    6662        62186 :   if (this->cond_ == NULL)
    6663         3874 :     b->add_statement(Statement::make_goto_unnamed_statement(top, end_loc));
    6664              :   else
    6665              :     {
    6666        58312 :       b->add_statement(Statement::make_unnamed_label_statement(entry));
    6667              : 
    6668        58312 :       Location cond_loc = this->cond_->location();
    6669        58312 :       Block* then_block = new Block(b, cond_loc);
    6670        58312 :       s = Statement::make_goto_unnamed_statement(top, cond_loc);
    6671        58312 :       then_block->add_statement(s);
    6672              : 
    6673        58312 :       s = Statement::make_if_statement(this->cond_, then_block, NULL, cond_loc);
    6674        58312 :       s->determine_types(gogo);
    6675        58312 :       b->add_statement(s);
    6676              :     }
    6677              : 
    6678        62186 :   Unnamed_label* brk = this->break_label_;
    6679        62186 :   if (brk != NULL)
    6680         5600 :     b->add_statement(Statement::make_unnamed_label_statement(brk));
    6681              : 
    6682        62186 :   b->set_end_location(end_loc);
    6683              : 
    6684        62186 :   Statement* bs = Statement::make_block_statement(b, loc);
    6685        62186 :   bs->block_statement()->set_is_lowered_for_statement();
    6686        62186 :   return bs;
    6687              : }
    6688              : 
    6689              : // Return the break label, creating it if necessary.
    6690              : 
    6691              : Unnamed_label*
    6692         5391 : For_statement::break_label()
    6693              : {
    6694         5391 :   if (this->break_label_ == NULL)
    6695         4186 :     this->break_label_ = new Unnamed_label(this->location());
    6696         5391 :   return this->break_label_;
    6697              : }
    6698              : 
    6699              : // Return the continue LABEL_EXPR.
    6700              : 
    6701              : Unnamed_label*
    6702         4887 : For_statement::continue_label()
    6703              : {
    6704         4887 :   if (this->continue_label_ == NULL)
    6705         2807 :     this->continue_label_ = new Unnamed_label(this->location());
    6706         4887 :   return this->continue_label_;
    6707              : }
    6708              : 
    6709              : // Set the break and continue labels a for statement.  This is used
    6710              : // when lowering a for range statement.
    6711              : 
    6712              : void
    6713        34114 : For_statement::set_break_continue_labels(Unnamed_label* break_label,
    6714              :                                          Unnamed_label* continue_label)
    6715              : {
    6716        34114 :   go_assert(this->break_label_ == NULL && this->continue_label_ == NULL);
    6717        34114 :   this->break_label_ = break_label;
    6718        34114 :   this->continue_label_ = continue_label;
    6719        34114 : }
    6720              : 
    6721              : // Whether the overall statement may fall through.
    6722              : 
    6723              : bool
    6724         1095 : For_statement::do_may_fall_through() const
    6725              : {
    6726              :   // A for loop is terminating if it has no condition and
    6727              :   // no break statement.
    6728         1095 :   if(this->cond_ != NULL)
    6729              :     return true;
    6730         1071 :   if(this->break_label_ != NULL)
    6731           12 :     return true;
    6732              :   return false;
    6733              : }
    6734              : 
    6735              : // Dump the AST representation for a for statement.
    6736              : 
    6737              : void
    6738            0 : For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    6739              : {
    6740            0 :   if (this->init_ != NULL && ast_dump_context->dump_subblocks())
    6741              :     {
    6742            0 :       ast_dump_context->print_indent();
    6743            0 :       ast_dump_context->indent();
    6744            0 :       ast_dump_context->ostream() << "// INIT  " << std::endl;
    6745            0 :       ast_dump_context->dump_block(this->init_);
    6746            0 :       ast_dump_context->unindent();
    6747              :     }
    6748            0 :   ast_dump_context->print_indent();
    6749            0 :   ast_dump_context->ostream() << "for ";
    6750            0 :   if (this->cond_ != NULL)
    6751            0 :     ast_dump_context->dump_expression(this->cond_);
    6752              : 
    6753            0 :   if (ast_dump_context->dump_subblocks())
    6754              :     {
    6755            0 :       ast_dump_context->ostream() << " {" << std::endl;
    6756            0 :       ast_dump_context->dump_block(this->statements_);
    6757            0 :       if (this->init_ != NULL)
    6758              :         {
    6759            0 :           ast_dump_context->print_indent();
    6760            0 :           ast_dump_context->ostream() << "// POST " << std::endl;
    6761            0 :           ast_dump_context->dump_block(this->post_);
    6762              :         }
    6763            0 :       ast_dump_context->unindent();
    6764              : 
    6765            0 :       ast_dump_context->print_indent();
    6766            0 :       ast_dump_context->ostream() << "}";
    6767              :     }
    6768              : 
    6769            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    6770            0 : }
    6771              : 
    6772              : // Make a for statement.
    6773              : 
    6774              : For_statement*
    6775        62188 : Statement::make_for_statement(Block* init, Expression* cond, Block* post,
    6776              :                               Location location)
    6777              : {
    6778        62188 :   return new For_statement(init, cond, post, location);
    6779              : }
    6780              : 
    6781              : // Class For_range_statement.
    6782              : 
    6783              : // Traversal.
    6784              : 
    6785              : int
    6786       137404 : For_range_statement::do_traverse(Traverse* traverse)
    6787              : {
    6788       137404 :   if (this->index_var_ != NULL)
    6789              :     {
    6790       136950 :       if (this->traverse_expression(traverse, &this->index_var_)
    6791              :           == TRAVERSE_EXIT)
    6792              :         return TRAVERSE_EXIT;
    6793              :     }
    6794       137404 :   if (this->value_var_ != NULL)
    6795              :     {
    6796       111400 :       if (this->traverse_expression(traverse, &this->value_var_)
    6797              :           == TRAVERSE_EXIT)
    6798              :         return TRAVERSE_EXIT;
    6799              :     }
    6800       137404 :   if (this->traverse_expression(traverse, &this->range_) == TRAVERSE_EXIT)
    6801              :     return TRAVERSE_EXIT;
    6802       137404 :   return this->statements_->traverse(traverse);
    6803              : }
    6804              : 
    6805              : void
    6806        43116 : For_range_statement::do_determine_types(Gogo* gogo)
    6807              : {
    6808        43116 :   if (this->index_var_ != NULL)
    6809        43025 :     this->index_var_->determine_type_no_context(gogo);
    6810        43116 :   if (this->value_var_ != NULL)
    6811        22280 :     this->value_var_->determine_type_no_context(gogo);
    6812        43116 :   this->range_->determine_type_no_context(gogo);
    6813        43116 :   this->statements_->determine_types(gogo);
    6814        43116 : }
    6815              : 
    6816              : void
    6817        25744 : For_range_statement::do_check_types(Gogo*)
    6818              : {
    6819        25744 :   Type* range_type = this->range_->type();
    6820              : 
    6821        25744 :   Type* index_type;
    6822        25744 :   Type* value_type = NULL;
    6823              : 
    6824        25744 :   if (range_type->points_to() != NULL
    6825          207 :       && range_type->points_to()->array_type() != NULL
    6826        25951 :       && !range_type->points_to()->is_slice_type())
    6827          207 :     range_type = range_type->points_to();
    6828              : 
    6829        25744 :   if (range_type->array_type() != NULL)
    6830              :     {
    6831        22962 :       index_type = Type::lookup_integer_type("int");
    6832        45924 :       value_type = range_type->array_type()->element_type();
    6833              :     }
    6834         2782 :   else if (range_type->is_string_type())
    6835              :     {
    6836          612 :       index_type = Type::lookup_integer_type("int");
    6837          612 :       value_type = Type::lookup_integer_type("rune");
    6838              :     }
    6839         2170 :   else if (range_type->map_type() != NULL)
    6840              :     {
    6841         4134 :       index_type = range_type->map_type()->key_type();
    6842         4134 :       value_type = range_type->map_type()->val_type();
    6843              :     }
    6844          103 :   else if (range_type->channel_type() != NULL)
    6845              :     {
    6846          206 :       if (!range_type->channel_type()->may_receive())
    6847            2 :         this->report_error(_("invalid receive on send-only channel"));
    6848          206 :       index_type = range_type->channel_type()->element_type();
    6849          103 :       if (this->value_var_ != NULL)
    6850              :         {
    6851            0 :           if (!this->value_var_->type()->is_error())
    6852            0 :             this->report_error(_("too many variables for range clause "
    6853              :                                  "with channel"));
    6854            0 :           this->set_is_error();
    6855            0 :           return;
    6856              :         }
    6857              :     }
    6858              :   else
    6859              :     {
    6860            0 :       this->report_error(_("range clause must have "
    6861              :                            "array, slice, string, map, or channel type"));
    6862            0 :       return;
    6863              :     }
    6864              : 
    6865        25744 :   if (this->index_var_ != NULL
    6866        25744 :       && !Assignment_statement::check_assignment_types(this->index_var_,
    6867              :                                                        index_type,
    6868              :                                                        this->location()))
    6869            0 :     this->set_is_error();
    6870        25744 :   if (this->value_var_ != NULL
    6871        25744 :       && !Assignment_statement::check_assignment_types(this->value_var_,
    6872              :                                                        value_type,
    6873              :                                                        this->location()))
    6874            0 :     this->set_is_error();
    6875              : }
    6876              : 
    6877              : // Lower a for range statement.  For simplicity we lower this into a
    6878              : // for statement, which will then be lowered in turn to goto
    6879              : // statements.
    6880              : 
    6881              : Statement*
    6882        34428 : For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
    6883              :                               Statement_inserter*)
    6884              : {
    6885        34428 :   if (this->classification() == STATEMENT_ERROR)
    6886            0 :     return Statement::make_error_statement(this->location());
    6887              : 
    6888        34428 :   Type* range_type = this->range_->type();
    6889        34428 :   if (range_type->points_to() != NULL
    6890         8893 :       && range_type->points_to()->array_type() != NULL
    6891        43321 :       && !range_type->points_to()->is_slice_type())
    6892         8893 :     range_type = range_type->points_to();
    6893              : 
    6894        34428 :   Type* index_type;
    6895        34428 :   Type* value_type = NULL;
    6896        34428 :   if (range_type->array_type() != NULL)
    6897              :     {
    6898        31648 :       index_type = Type::lookup_integer_type("int");
    6899        63296 :       value_type = range_type->array_type()->element_type();
    6900              :     }
    6901         2780 :   else if (range_type->is_string_type())
    6902              :     {
    6903          612 :       index_type = Type::lookup_integer_type("int");
    6904          612 :       value_type = Type::lookup_integer_type("rune");
    6905              :     }
    6906         2168 :   else if (range_type->map_type() != NULL)
    6907              :     {
    6908         4134 :       index_type = range_type->map_type()->key_type();
    6909         4134 :       value_type = range_type->map_type()->val_type();
    6910              :     }
    6911          101 :   else if (range_type->channel_type() != NULL)
    6912              :     {
    6913          202 :       index_type = range_type->channel_type()->element_type();
    6914          101 :       go_assert(this->value_var_ == NULL);
    6915              :     }
    6916              :   else
    6917            0 :     go_unreachable();
    6918              : 
    6919              :   // If there is only one iteration variable, and len(this->range_) is
    6920              :   // constant, then we do not evaluate the range variable.  len(x) is
    6921              :   // a contant if x is a string constant or if x is an array.  If x is
    6922              :   // a constant then evaluating it won't make any difference, so the
    6923              :   // only case to consider is when x is an array whose length is constant.
    6924        34428 :   bool eval = true;
    6925        22280 :   if ((this->value_var_ == NULL || this->value_var_->is_sink_expression())
    6926        45786 :       && range_type->array_type() != NULL
    6927        11358 :       && !range_type->is_slice_type()
    6928        43732 :       && Builtin_call_expression::array_len_is_constant(this->range_))
    6929              :     eval = false;
    6930              : 
    6931        34428 :   Location loc = this->location();
    6932        34428 :   Block* temp_block = new Block(enclosing, loc);
    6933              : 
    6934        34428 :   Expression* orig_range_expr = this->range_;
    6935        34428 :   Named_object* range_object = NULL;
    6936        34428 :   Temporary_statement* range_temp = NULL;
    6937        34428 :   if (eval)
    6938              :     {
    6939        25128 :       Var_expression* ve = this->range_->var_expression();
    6940        25128 :       if (ve != NULL)
    6941        14959 :         range_object = ve->named_object();
    6942              :       else
    6943              :         {
    6944        10169 :           range_temp = Statement::make_temporary(NULL, this->range_, loc);
    6945        10169 :           temp_block->add_statement(range_temp);
    6946        10169 :           this->range_ = NULL;
    6947              :         }
    6948              :     }
    6949              : 
    6950              :   // Try to match "range clear" patterns and rewrite to simple runtime
    6951              :   // calls.
    6952        34428 :   if (range_type->map_type() != NULL)
    6953              :     {
    6954         2067 :       Statement* clear = this->lower_map_range_clear(gogo,
    6955              :                                                      range_type,
    6956              :                                                      enclosing,
    6957              :                                                      orig_range_expr,
    6958              :                                                      range_object,
    6959              :                                                      range_temp, loc);
    6960         2067 :       if (clear != NULL)
    6961              :         {
    6962           33 :           if (gogo->debug_optimization())
    6963            1 :             go_debug(loc, "map range clear");
    6964           33 :           clear->determine_types(gogo);
    6965           33 :           temp_block->add_statement(clear);
    6966           33 :           return Statement::make_block_statement(temp_block, loc);
    6967              :         }
    6968              :     }
    6969        32361 :   else if (range_type->array_type() != NULL)
    6970              :     {
    6971              :       // Slice or array.
    6972        31648 :       Statement* clear = this->lower_array_range_clear(gogo,
    6973              :                                                        range_type,
    6974              :                                                        orig_range_expr,
    6975              :                                                        temp_block,
    6976              :                                                        range_object,
    6977              :                                                        range_temp, loc);
    6978        31648 :       if (clear != NULL)
    6979              :         {
    6980          281 :           if (gogo->debug_optimization())
    6981            2 :             go_debug(loc, "array range clear");
    6982          281 :           clear->determine_types(gogo);
    6983          281 :           temp_block->add_statement(clear);
    6984          281 :           return Statement::make_block_statement(temp_block, loc);
    6985              :         }
    6986              :     }
    6987              : 
    6988        34114 :   Temporary_statement* index_temp = Statement::make_temporary(index_type,
    6989              :                                                               NULL, loc);
    6990        34114 :   temp_block->add_statement(index_temp);
    6991              : 
    6992        34114 :   Temporary_statement* value_temp = NULL;
    6993        34114 :   if (this->value_var_ != NULL && !this->value_var_->is_sink_expression())
    6994              :     {
    6995        22252 :       value_temp = Statement::make_temporary(value_type, NULL, loc);
    6996        22252 :       temp_block->add_statement(value_temp);
    6997              :     }
    6998              : 
    6999        34114 :   Block* body = new Block(temp_block, loc);
    7000              : 
    7001        34114 :   Block* init;
    7002        34114 :   Expression* cond;
    7003        34114 :   Block* iter_init;
    7004        34114 :   Block* post;
    7005              : 
    7006              :   // Arrange to do a loop appropriate for the type.  We will produce
    7007              :   //   for INIT ; COND ; POST {
    7008              :   //           ITER_INIT
    7009              :   //           INDEX = INDEX_TEMP
    7010              :   //           VALUE = VALUE_TEMP // If there is a value
    7011              :   //           original statements
    7012              :   //   }
    7013              : 
    7014        34114 :   if (range_type->is_slice_type())
    7015        21657 :     this->lower_range_slice(gogo, temp_block, body, range_object, range_temp,
    7016              :                             index_temp, value_temp, &init, &cond, &iter_init,
    7017              :                             &post);
    7018        12457 :   else if (range_type->array_type() != NULL)
    7019         9710 :     this->lower_range_array(gogo, temp_block, body, range_object, range_temp,
    7020              :                             index_temp, value_temp, &init, &cond, &iter_init,
    7021              :                             &post);
    7022         2747 :   else if (range_type->is_string_type())
    7023          612 :     this->lower_range_string(gogo, temp_block, body, range_object, range_temp,
    7024              :                              index_temp, value_temp, &init, &cond, &iter_init,
    7025              :                              &post);
    7026         2135 :   else if (range_type->map_type() != NULL)
    7027         4068 :     this->lower_range_map(gogo, range_type->map_type(), temp_block, body,
    7028              :                           range_object, range_temp, index_temp, value_temp,
    7029              :                           &init, &cond, &iter_init, &post);
    7030          101 :   else if (range_type->channel_type() != NULL)
    7031          101 :     this->lower_range_channel(gogo, temp_block, body, range_object, range_temp,
    7032              :                               index_temp, value_temp, &init, &cond, &iter_init,
    7033              :                               &post);
    7034              :   else
    7035            0 :     go_unreachable();
    7036              : 
    7037        34114 :   if (iter_init != NULL)
    7038        23037 :     body->add_statement(Statement::make_block_statement(iter_init, loc));
    7039              : 
    7040        34114 :   if (this->index_var_ != NULL)
    7041              :     {
    7042        34024 :       Statement* assign;
    7043        34024 :       Expression* index_ref =
    7044        34024 :         Expression::make_temporary_reference(index_temp, loc);
    7045        34024 :       if (this->value_var_ == NULL || this->value_var_->is_sink_expression())
    7046        11772 :         assign = Statement::make_assignment(this->index_var_, index_ref, loc);
    7047              :       else
    7048              :         {
    7049        22252 :           Expression_list* lhs = new Expression_list();
    7050        22252 :           lhs->push_back(this->index_var_);
    7051        22252 :           lhs->push_back(this->value_var_);
    7052              : 
    7053        22252 :           Expression_list* rhs = new Expression_list();
    7054        22252 :           rhs->push_back(index_ref);
    7055        22252 :           rhs->push_back(Expression::make_temporary_reference(value_temp, loc));
    7056              : 
    7057        22252 :           assign = Statement::make_tuple_assignment(lhs, rhs, loc);
    7058              :         }
    7059        34024 :       assign->determine_types(gogo);
    7060        34024 :       body->add_statement(assign);
    7061              :     }
    7062              : 
    7063        34114 :   body->add_statement(Statement::make_block_statement(this->statements_, loc));
    7064              : 
    7065        34114 :   body->set_end_location(this->statements_->end_location());
    7066              : 
    7067        34114 :   For_statement* loop = Statement::make_for_statement(init, cond, post,
    7068              :                                                       this->location());
    7069        34114 :   loop->add_statements(body);
    7070        34114 :   loop->determine_types(gogo);
    7071        34114 :   loop->set_break_continue_labels(this->break_label_, this->continue_label_);
    7072              : 
    7073        34114 :   temp_block->add_statement(loop);
    7074              : 
    7075        34114 :   return Statement::make_block_statement(temp_block, loc);
    7076              : }
    7077              : 
    7078              : // Return a reference to the range, which may be in RANGE_OBJECT or in
    7079              : // RANGE_TEMP.
    7080              : 
    7081              : Expression*
    7082        26352 : For_range_statement::make_range_ref(Named_object* range_object,
    7083              :                                     Temporary_statement* range_temp,
    7084              :                                     Location loc)
    7085              : {
    7086        26352 :   if (range_object != NULL)
    7087        16021 :     return Expression::make_var_reference(range_object, loc);
    7088              :   else
    7089        10331 :     return Expression::make_temporary_reference(range_temp, loc);
    7090              : }
    7091              : 
    7092              : // Return a call to the predeclared function FUNCNAME passing a
    7093              : // reference to the temporary variable ARG.
    7094              : 
    7095              : Call_expression*
    7096        32260 : For_range_statement::call_builtin(Gogo* gogo, const char* funcname,
    7097              :                                   Expression* arg,
    7098              :                                   Location loc)
    7099              : {
    7100        32260 :   Named_object* no = gogo->lookup_global(funcname);
    7101        32260 :   go_assert(no != NULL && no->is_function_declaration());
    7102        32260 :   Expression* func = Expression::make_func_reference(no, NULL, loc);
    7103        32260 :   Expression_list* params = new Expression_list();
    7104        32260 :   params->push_back(arg);
    7105        32260 :   return Expression::make_call(func, params, false, loc);
    7106              : }
    7107              : 
    7108              : // Lower a for range over an array.
    7109              : 
    7110              : void
    7111         9710 : For_range_statement::lower_range_array(Gogo* gogo,
    7112              :                                        Block* enclosing,
    7113              :                                        Block* body_block,
    7114              :                                        Named_object* range_object,
    7115              :                                        Temporary_statement* range_temp,
    7116              :                                        Temporary_statement* index_temp,
    7117              :                                        Temporary_statement* value_temp,
    7118              :                                        Block** pinit,
    7119              :                                        Expression** pcond,
    7120              :                                        Block** piter_init,
    7121              :                                        Block** ppost)
    7122              : {
    7123         9710 :   Location loc = this->location();
    7124              : 
    7125              :   // The loop we generate:
    7126              :   //   len_temp := len(range)
    7127              :   //   range_temp := range
    7128              :   //   for index_temp = 0; index_temp < len_temp; index_temp++ {
    7129              :   //           value_temp = range_temp[index_temp]
    7130              :   //           index = index_temp
    7131              :   //           value = value_temp
    7132              :   //           original body
    7133              :   //   }
    7134              : 
    7135              :   // Set *PINIT to
    7136              :   //   var len_temp int
    7137              :   //   len_temp = len(range)
    7138              :   //   index_temp = 0
    7139              : 
    7140         9710 :   Block* init = new Block(enclosing, loc);
    7141              : 
    7142         9710 :   Expression* len_arg;
    7143         9710 :   if (range_object == NULL && range_temp == NULL)
    7144              :     {
    7145              :       // Don't evaluate this->range_, just get its length.
    7146         9209 :       len_arg = this->range_;
    7147              :     }
    7148              :   else
    7149              :     {
    7150          501 :       Expression* ref = this->make_range_ref(range_object, range_temp, loc);
    7151          501 :       range_temp = Statement::make_temporary(NULL, ref, loc);
    7152          501 :       range_temp->determine_types(gogo);
    7153          501 :       init->add_statement(range_temp);
    7154          501 :       len_arg = ref;
    7155              :     }
    7156         9710 :   Expression* len_call = this->call_builtin(gogo, "len", len_arg, loc);
    7157         9710 :   Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
    7158              :                                                             len_call, loc);
    7159         9710 :   len_temp->determine_types(gogo);
    7160         9710 :   init->add_statement(len_temp);
    7161              : 
    7162         9710 :   Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
    7163              : 
    7164         9710 :   Temporary_reference_expression* tref =
    7165         9710 :     Expression::make_temporary_reference(index_temp, loc);
    7166         9710 :   tref->set_is_lvalue();
    7167         9710 :   Statement* s = Statement::make_assignment(tref, zexpr, loc);
    7168         9710 :   s->determine_types(gogo);
    7169         9710 :   init->add_statement(s);
    7170              : 
    7171         9710 :   *pinit = init;
    7172              : 
    7173              :   // Set *PCOND to
    7174              :   //   index_temp < len_temp
    7175              : 
    7176         9710 :   Expression* ref = Expression::make_temporary_reference(index_temp, loc);
    7177         9710 :   Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
    7178         9710 :   Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
    7179              : 
    7180         9710 :   *pcond = lt;
    7181              : 
    7182              :   // Set *PITER_INIT to
    7183              :   //   value_temp = range[index_temp]
    7184              : 
    7185         9710 :   Block* iter_init = NULL;
    7186         9710 :   if (value_temp != NULL)
    7187              :     {
    7188          497 :       iter_init = new Block(body_block, loc);
    7189              : 
    7190          497 :       ref = Expression::make_temporary_reference(range_temp, loc);
    7191          497 :       ref2 = Expression::make_temporary_reference(index_temp, loc);
    7192          497 :       Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
    7193              : 
    7194          497 :       tref = Expression::make_temporary_reference(value_temp, loc);
    7195          497 :       tref->set_is_lvalue();
    7196          497 :       s = Statement::make_assignment(tref, index, loc);
    7197          497 :       s->determine_types(gogo);
    7198              : 
    7199          497 :       iter_init->add_statement(s);
    7200              :     }
    7201         9710 :   *piter_init = iter_init;
    7202              : 
    7203              :   // Set *PPOST to
    7204              :   //   index_temp++
    7205              : 
    7206         9710 :   Block* post = new Block(enclosing, loc);
    7207         9710 :   tref = Expression::make_temporary_reference(index_temp, loc);
    7208         9710 :   tref->set_is_lvalue();
    7209         9710 :   s = Statement::make_inc_statement(tref);
    7210         9710 :   s->determine_types(gogo);
    7211         9710 :   post->add_statement(s);
    7212         9710 :   *ppost = post;
    7213         9710 : }
    7214              : 
    7215              : // Lower a for range over a slice.
    7216              : 
    7217              : void
    7218        21657 : For_range_statement::lower_range_slice(Gogo* gogo,
    7219              :                                        Block* enclosing,
    7220              :                                        Block* body_block,
    7221              :                                        Named_object* range_object,
    7222              :                                        Temporary_statement* range_temp,
    7223              :                                        Temporary_statement* index_temp,
    7224              :                                        Temporary_statement* value_temp,
    7225              :                                        Block** pinit,
    7226              :                                        Expression** pcond,
    7227              :                                        Block** piter_init,
    7228              :                                        Block** ppost)
    7229              : {
    7230        21657 :   Location loc = this->location();
    7231              : 
    7232              :   // The loop we generate:
    7233              :   //   for_temp := range
    7234              :   //   len_temp := len(for_temp)
    7235              :   //   for index_temp = 0; index_temp < len_temp; index_temp++ {
    7236              :   //           value_temp = for_temp[index_temp]
    7237              :   //           index = index_temp
    7238              :   //           value = value_temp
    7239              :   //           original body
    7240              :   //   }
    7241              :   //
    7242              :   // Using for_temp means that we don't need to check bounds when
    7243              :   // fetching range_temp[index_temp].
    7244              : 
    7245              :   // Set *PINIT to
    7246              :   //   range_temp := range
    7247              :   //   var len_temp int
    7248              :   //   len_temp = len(range_temp)
    7249              :   //   index_temp = 0
    7250              : 
    7251        21657 :   Block* init = new Block(enclosing, loc);
    7252              : 
    7253        21657 :   Expression* ref = this->make_range_ref(range_object, range_temp, loc);
    7254        21657 :   Temporary_statement* for_temp = Statement::make_temporary(NULL, ref, loc);
    7255        21657 :   for_temp->determine_types(gogo);
    7256        21657 :   init->add_statement(for_temp);
    7257              : 
    7258        21657 :   ref = Expression::make_temporary_reference(for_temp, loc);
    7259        21657 :   Expression* len_call = this->call_builtin(gogo, "len", ref, loc);
    7260        21657 :   Temporary_statement* len_temp = Statement::make_temporary(index_temp->type(),
    7261              :                                                             len_call, loc);
    7262        21657 :   len_temp->determine_types(gogo);
    7263        21657 :   init->add_statement(len_temp);
    7264              : 
    7265        21657 :   Expression* zexpr = Expression::make_integer_ul(0, NULL, loc);
    7266              : 
    7267        21657 :   Temporary_reference_expression* tref =
    7268        21657 :     Expression::make_temporary_reference(index_temp, loc);
    7269        21657 :   tref->set_is_lvalue();
    7270        21657 :   Statement* s = Statement::make_assignment(tref, zexpr, loc);
    7271        21657 :   s->determine_types(gogo);
    7272        21657 :   init->add_statement(s);
    7273              : 
    7274        21657 :   *pinit = init;
    7275              : 
    7276              :   // Set *PCOND to
    7277              :   //   index_temp < len_temp
    7278              : 
    7279        21657 :   ref = Expression::make_temporary_reference(index_temp, loc);
    7280        21657 :   Expression* ref2 = Expression::make_temporary_reference(len_temp, loc);
    7281        21657 :   Expression* lt = Expression::make_binary(OPERATOR_LT, ref, ref2, loc);
    7282              : 
    7283        21657 :   *pcond = lt;
    7284              : 
    7285              :   // Set *PITER_INIT to
    7286              :   //   value_temp = range[index_temp]
    7287              : 
    7288        21657 :   Block* iter_init = NULL;
    7289        21657 :   if (value_temp != NULL)
    7290              :     {
    7291        19793 :       iter_init = new Block(body_block, loc);
    7292              : 
    7293        19793 :       ref = Expression::make_temporary_reference(for_temp, loc);
    7294        19793 :       ref2 = Expression::make_temporary_reference(index_temp, loc);
    7295        19793 :       Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc);
    7296              : 
    7297        19793 :       tref = Expression::make_temporary_reference(value_temp, loc);
    7298        19793 :       tref->set_is_lvalue();
    7299        19793 :       s = Statement::make_assignment(tref, index, loc);
    7300        19793 :       s->determine_types(gogo);
    7301              : 
    7302        19793 :       iter_init->add_statement(s);
    7303              :     }
    7304        21657 :   *piter_init = iter_init;
    7305              : 
    7306              :   // Set *PPOST to
    7307              :   //   index_temp++
    7308              : 
    7309        21657 :   Block* post = new Block(enclosing, loc);
    7310        21657 :   tref = Expression::make_temporary_reference(index_temp, loc);
    7311        21657 :   tref->set_is_lvalue();
    7312        21657 :   s = Statement::make_inc_statement(tref);
    7313        21657 :   s->determine_types(gogo);
    7314        21657 :   post->add_statement(s);
    7315        21657 :   *ppost = post;
    7316        21657 : }
    7317              : 
    7318              : // Lower a for range over a string.
    7319              : 
    7320              : void
    7321          612 : For_range_statement::lower_range_string(Gogo* gogo,
    7322              :                                         Block* enclosing,
    7323              :                                         Block* body_block,
    7324              :                                         Named_object* range_object,
    7325              :                                         Temporary_statement* range_temp,
    7326              :                                         Temporary_statement* index_temp,
    7327              :                                         Temporary_statement* value_temp,
    7328              :                                         Block** pinit,
    7329              :                                         Expression** pcond,
    7330              :                                         Block** piter_init,
    7331              :                                         Block** ppost)
    7332              : {
    7333          612 :   Location loc = this->location();
    7334              : 
    7335              :   // The loop we generate:
    7336              :   //   len_temp := len(range)
    7337              :   //   var next_index_temp int
    7338              :   //   for index_temp = 0; index_temp < len_temp; index_temp = next_index_temp {
    7339              :   //           value_temp = rune(range[index_temp])
    7340              :   //           if value_temp < utf8.RuneSelf {
    7341              :   //                   next_index_temp = index_temp + 1
    7342              :   //           } else {
    7343              :   //                   value_temp, next_index_temp = decoderune(range, index_temp)
    7344              :   //           }
    7345              :   //           index = index_temp
    7346              :   //           value = value_temp
    7347              :   //           // original body
    7348              :   //   }
    7349              : 
    7350              :   // Set *PINIT to
    7351              :   //   len_temp := len(range)
    7352              :   //   var next_index_temp int
    7353              :   //   index_temp = 0
    7354              :   //   var value_temp rune // if value_temp not passed in
    7355              : 
    7356          612 :   Block* init = new Block(enclosing, loc);
    7357              : 
    7358          612 :   Expression* ref = this->make_range_ref(range_object, range_temp, loc);
    7359          612 :   Call_expression* call = this->call_builtin(gogo, "len", ref, loc);
    7360          612 :   Temporary_statement* len_temp =
    7361          612 :     Statement::make_temporary(index_temp->type(), call, loc);
    7362          612 :   len_temp->determine_types(gogo);
    7363          612 :   init->add_statement(len_temp);
    7364              : 
    7365          612 :   Temporary_statement* next_index_temp =
    7366          612 :     Statement::make_temporary(index_temp->type(), NULL, loc);
    7367          612 :   init->add_statement(next_index_temp);
    7368              : 
    7369          612 :   Temporary_reference_expression* index_ref =
    7370          612 :     Expression::make_temporary_reference(index_temp, loc);
    7371          612 :   index_ref->set_is_lvalue();
    7372          612 :   Expression* zexpr = Expression::make_integer_ul(0, index_temp->type(), loc);
    7373          612 :   Statement* s = Statement::make_assignment(index_ref, zexpr, loc);
    7374          612 :   s->determine_types(gogo);
    7375          612 :   init->add_statement(s);
    7376              : 
    7377          612 :   Type* rune_type;
    7378          612 :   if (value_temp != NULL)
    7379          561 :     rune_type = value_temp->type();
    7380              :   else
    7381              :     {
    7382           51 :       rune_type = Type::lookup_integer_type("rune");
    7383           51 :       value_temp = Statement::make_temporary(rune_type, NULL, loc);
    7384           51 :       init->add_statement(value_temp);
    7385              :     }
    7386              : 
    7387          612 :   *pinit = init;
    7388              : 
    7389              :   // Set *PCOND to
    7390              :   //   index_temp < len_temp
    7391              : 
    7392          612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7393          612 :   Expression* len_ref =
    7394          612 :     Expression::make_temporary_reference(len_temp, loc);
    7395          612 :   *pcond = Expression::make_binary(OPERATOR_LT, index_ref, len_ref, loc);
    7396              : 
    7397              :   // Set *PITER_INIT to
    7398              :   //   value_temp = rune(range[index_temp])
    7399              :   //   if value_temp < utf8.RuneSelf {
    7400              :   //           next_index_temp = index_temp + 1
    7401              :   //   } else {
    7402              :   //           value_temp, next_index_temp = decoderune(range, index_temp)
    7403              :   //   }
    7404              : 
    7405          612 :   Block* iter_init = new Block(body_block, loc);
    7406              : 
    7407          612 :   ref = this->make_range_ref(range_object, range_temp, loc);
    7408          612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7409          612 :   ref = Expression::make_string_index(ref, index_ref, NULL, loc);
    7410          612 :   ref = Expression::make_cast(rune_type, ref, loc);
    7411          612 :   Temporary_reference_expression* value_ref =
    7412          612 :     Expression::make_temporary_reference(value_temp, loc);
    7413          612 :   value_ref->set_is_lvalue();
    7414          612 :   s = Statement::make_assignment(value_ref, ref, loc);
    7415          612 :   s->determine_types(gogo);
    7416          612 :   iter_init->add_statement(s);
    7417              : 
    7418          612 :   value_ref = Expression::make_temporary_reference(value_temp, loc);
    7419          612 :   Expression* rune_self = Expression::make_integer_ul(0x80, rune_type, loc);
    7420          612 :   Expression* cond = Expression::make_binary(OPERATOR_LT, value_ref, rune_self,
    7421              :                                              loc);
    7422              : 
    7423          612 :   Block* then_block = new Block(iter_init, loc);
    7424              : 
    7425          612 :   Temporary_reference_expression* lhs =
    7426          612 :     Expression::make_temporary_reference(next_index_temp, loc);
    7427          612 :   lhs->set_is_lvalue();
    7428          612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7429          612 :   Expression* one = Expression::make_integer_ul(1, index_temp->type(), loc);
    7430          612 :   Expression* sum = Expression::make_binary(OPERATOR_PLUS, index_ref, one,
    7431              :                                             loc);
    7432          612 :   s = Statement::make_assignment(lhs, sum, loc);
    7433          612 :   s->determine_types(gogo);
    7434          612 :   then_block->add_statement(s);
    7435              : 
    7436          612 :   Block* else_block = new Block(iter_init, loc);
    7437              : 
    7438          612 :   ref = this->make_range_ref(range_object, range_temp, loc);
    7439          612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7440          612 :   call = Runtime::make_call(gogo, Runtime::DECODERUNE, loc, 2, ref, index_ref);
    7441              : 
    7442          612 :   value_ref = Expression::make_temporary_reference(value_temp, loc);
    7443          612 :   value_ref->set_is_lvalue();
    7444          612 :   Expression* res = Expression::make_call_result(call, 0);
    7445          612 :   s = Statement::make_assignment(value_ref, res, loc);
    7446          612 :   s->determine_types(gogo);
    7447          612 :   else_block->add_statement(s);
    7448              : 
    7449          612 :   lhs = Expression::make_temporary_reference(next_index_temp, loc);
    7450          612 :   lhs->set_is_lvalue();
    7451          612 :   res = Expression::make_call_result(call, 1);
    7452          612 :   s = Statement::make_assignment(lhs, res, loc);
    7453          612 :   s->determine_types(gogo);
    7454          612 :   else_block->add_statement(s);
    7455              : 
    7456          612 :   s = Statement::make_if_statement(cond, then_block, else_block, loc);
    7457          612 :   s->determine_types(gogo);
    7458          612 :   iter_init->add_statement(s);
    7459              : 
    7460          612 :   *piter_init = iter_init;
    7461              : 
    7462              :   // Set *PPOST to
    7463              :   //   index_temp = next_index_temp
    7464              : 
    7465          612 :   Block* post = new Block(enclosing, loc);
    7466              : 
    7467          612 :   index_ref = Expression::make_temporary_reference(index_temp, loc);
    7468          612 :   index_ref->set_is_lvalue();
    7469          612 :   ref = Expression::make_temporary_reference(next_index_temp, loc);
    7470          612 :   s = Statement::make_assignment(index_ref, ref, loc);
    7471          612 :   s->determine_types(gogo);
    7472              : 
    7473          612 :   post->add_statement(s);
    7474          612 :   *ppost = post;
    7475          612 : }
    7476              : 
    7477              : // Lower a for range over a map.
    7478              : 
    7479              : void
    7480         2034 : For_range_statement::lower_range_map(Gogo* gogo,
    7481              :                                      Map_type* map_type,
    7482              :                                      Block* enclosing,
    7483              :                                      Block* body_block,
    7484              :                                      Named_object* range_object,
    7485              :                                      Temporary_statement* range_temp,
    7486              :                                      Temporary_statement* index_temp,
    7487              :                                      Temporary_statement* value_temp,
    7488              :                                      Block** pinit,
    7489              :                                      Expression** pcond,
    7490              :                                      Block** piter_init,
    7491              :                                      Block** ppost)
    7492              : {
    7493         2034 :   Location loc = this->location();
    7494              : 
    7495              :   // The runtime uses a struct to handle ranges over a map.  The
    7496              :   // struct is built by Map_type::hiter_type for a specific map type.
    7497              : 
    7498              :   // The loop we generate:
    7499              :   //   var hiter map_iteration_struct
    7500              :   //   for mapiterinit(type, range, &hiter); hiter.key != nil; mapiternext(&hiter) {
    7501              :   //           index_temp = *hiter.key
    7502              :   //           value_temp = *hiter.val
    7503              :   //           index = index_temp
    7504              :   //           value = value_temp
    7505              :   //           original body
    7506              :   //   }
    7507              : 
    7508              :   // Set *PINIT to
    7509              :   //   var hiter map_iteration_struct
    7510              :   //   runtime.mapiterinit(type, range, &hiter)
    7511              : 
    7512         2034 :   Block* init = new Block(enclosing, loc);
    7513              : 
    7514         2034 :   Type* map_iteration_type = map_type->hiter_type(gogo);
    7515         2034 :   Temporary_statement* hiter = Statement::make_temporary(map_iteration_type,
    7516              :                                                          NULL, loc);
    7517         2034 :   init->add_statement(hiter);
    7518              : 
    7519         2034 :   Expression* p1 = Expression::make_type_descriptor(map_type, loc);
    7520         2034 :   Expression* p2 = this->make_range_ref(range_object, range_temp, loc);
    7521         2034 :   Expression* ref = Expression::make_temporary_reference(hiter, loc);
    7522         2034 :   Expression* p3 = Expression::make_unary(OPERATOR_AND, ref, loc);
    7523         2034 :   Expression* call = Runtime::make_call(gogo, Runtime::MAPITERINIT, loc, 3,
    7524              :                                         p1, p2, p3);
    7525         2034 :   Statement* s = Statement::make_statement(call, true);
    7526         2034 :   s->determine_types(gogo);
    7527         2034 :   init->add_statement(s);
    7528              : 
    7529         2034 :   *pinit = init;
    7530              : 
    7531              :   // Set *PCOND to
    7532              :   //   hiter.key != nil
    7533              : 
    7534         2034 :   ref = Expression::make_temporary_reference(hiter, loc);
    7535         2034 :   ref = Expression::make_field_reference(ref, 0, loc);
    7536         2034 :   Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, ref,
    7537              :                                            Expression::make_nil(loc),
    7538              :                                            loc);
    7539         2034 :   *pcond = ne;
    7540              : 
    7541              :   // Set *PITER_INIT to
    7542              :   //   index_temp = *hiter.key
    7543              :   //   value_temp = *hiter.val
    7544              : 
    7545         2034 :   Block* iter_init = new Block(body_block, loc);
    7546              : 
    7547         2034 :   Expression* lhs = Expression::make_temporary_reference(index_temp, loc);
    7548         2034 :   Expression* rhs = Expression::make_temporary_reference(hiter, loc);
    7549         2034 :   rhs = Expression::make_field_reference(ref, 0, loc);
    7550         2034 :   rhs = Expression::make_dereference(ref, Expression::NIL_CHECK_NOT_NEEDED,
    7551              :                                      loc);
    7552         2034 :   Statement* set = Statement::make_assignment(lhs, rhs, loc);
    7553         2034 :   set->determine_types(gogo);
    7554         2034 :   iter_init->add_statement(set);
    7555              : 
    7556         2034 :   if (value_temp != NULL)
    7557              :     {
    7558         1401 :       lhs = Expression::make_temporary_reference(value_temp, loc);
    7559         1401 :       rhs = Expression::make_temporary_reference(hiter, loc);
    7560         1401 :       rhs = Expression::make_field_reference(rhs, 1, loc);
    7561         1401 :       rhs = Expression::make_dereference(rhs, Expression::NIL_CHECK_NOT_NEEDED,
    7562              :                                          loc);
    7563         1401 :       set = Statement::make_assignment(lhs, rhs, loc);
    7564         1401 :       set->determine_types(gogo);
    7565         1401 :       iter_init->add_statement(set);
    7566              :     }
    7567              : 
    7568         2034 :   *piter_init = iter_init;
    7569              : 
    7570              :   // Set *PPOST to
    7571              :   //   mapiternext(&hiter)
    7572              : 
    7573         2034 :   Block* post = new Block(enclosing, loc);
    7574              : 
    7575         2034 :   ref = Expression::make_temporary_reference(hiter, loc);
    7576         2034 :   p1 = Expression::make_unary(OPERATOR_AND, ref, loc);
    7577         2034 :   call = Runtime::make_call(gogo, Runtime::MAPITERNEXT, loc, 1, p1);
    7578         2034 :   s = Statement::make_statement(call, true);
    7579         2034 :   s->determine_types(gogo);
    7580         2034 :   post->add_statement(s);
    7581              : 
    7582         2034 :   *ppost = post;
    7583         2034 : }
    7584              : 
    7585              : // Lower a for range over a channel.
    7586              : 
    7587              : void
    7588          101 : For_range_statement::lower_range_channel(Gogo* gogo,
    7589              :                                          Block*,
    7590              :                                          Block* body_block,
    7591              :                                          Named_object* range_object,
    7592              :                                          Temporary_statement* range_temp,
    7593              :                                          Temporary_statement* index_temp,
    7594              :                                          Temporary_statement* value_temp,
    7595              :                                          Block** pinit,
    7596              :                                          Expression** pcond,
    7597              :                                          Block** piter_init,
    7598              :                                          Block** ppost)
    7599              : {
    7600          101 :   go_assert(value_temp == NULL);
    7601              : 
    7602          101 :   Location loc = this->location();
    7603              : 
    7604              :   // The loop we generate:
    7605              :   //   for {
    7606              :   //           index_temp, ok_temp = <-range
    7607              :   //           if !ok_temp {
    7608              :   //                   break
    7609              :   //           }
    7610              :   //           index = index_temp
    7611              :   //           original body
    7612              :   //   }
    7613              : 
    7614              :   // We have no initialization code, no condition, and no post code.
    7615              : 
    7616          101 :   *pinit = NULL;
    7617          101 :   *pcond = NULL;
    7618          101 :   *ppost = NULL;
    7619              : 
    7620              :   // Set *PITER_INIT to
    7621              :   //   index_temp, ok_temp = <-range
    7622              :   //   if !ok_temp {
    7623              :   //           break
    7624              :   //   }
    7625              : 
    7626          101 :   Block* iter_init = new Block(body_block, loc);
    7627              : 
    7628          101 :   Temporary_statement* ok_temp =
    7629          101 :     Statement::make_temporary(Type::lookup_bool_type(), NULL, loc);
    7630          101 :   iter_init->add_statement(ok_temp);
    7631              : 
    7632          101 :   Expression* cref = this->make_range_ref(range_object, range_temp, loc);
    7633          101 :   Temporary_reference_expression* iref =
    7634          101 :     Expression::make_temporary_reference(index_temp, loc);
    7635          101 :   iref->set_is_lvalue();
    7636          101 :   Temporary_reference_expression* oref =
    7637          101 :     Expression::make_temporary_reference(ok_temp, loc);
    7638          101 :   oref->set_is_lvalue();
    7639          101 :   Statement* s = Statement::make_tuple_receive_assignment(iref, oref, cref,
    7640              :                                                           loc);
    7641          101 :   s->determine_types(gogo);
    7642          101 :   iter_init->add_statement(s);
    7643              : 
    7644          101 :   Block* then_block = new Block(iter_init, loc);
    7645          101 :   s = Statement::make_break_statement(this->break_label(), loc);
    7646          101 :   then_block->add_statement(s);
    7647              : 
    7648          101 :   oref = Expression::make_temporary_reference(ok_temp, loc);
    7649          101 :   Expression* cond = Expression::make_unary(OPERATOR_NOT, oref, loc);
    7650          101 :   s = Statement::make_if_statement(cond, then_block, NULL, loc);
    7651          101 :   s->determine_types(gogo);
    7652          101 :   iter_init->add_statement(s);
    7653              : 
    7654          101 :   *piter_init = iter_init;
    7655          101 : }
    7656              : 
    7657              : // Match
    7658              : //
    7659              : //   for k := range m { delete(m, k) }
    7660              : //
    7661              : // Lower it to runtime.mapclear(TYPE, m) on match, return the statement
    7662              : // containing the call.  Return NULL otherwise.
    7663              : 
    7664              : Statement*
    7665         2067 : For_range_statement::lower_map_range_clear(Gogo* gogo,
    7666              :                                            Type* map_type,
    7667              :                                            Block* enclosing,
    7668              :                                            Expression* orig_range_expr,
    7669              :                                            Named_object* range_object,
    7670              :                                            Temporary_statement* range_temp,
    7671              :                                            Location loc)
    7672              : {
    7673         2067 :   if (this->value_var_ != NULL)
    7674              :     return NULL;
    7675          645 :   if (this->index_var_ == NULL)
    7676              :     return NULL;
    7677              : 
    7678              :   // Require the loop index be a new variable.  We cannot rewrite
    7679              :   // if it is used outside of the loop.
    7680         2664 :   Var_expression* index_ve = this->index_var_->var_expression();
    7681          630 :   if (index_ve == NULL)
    7682              :     return NULL;
    7683          630 :   Named_object* index_no = index_ve->named_object();
    7684          630 :   if (enclosing->bindings()->lookup_local(index_no->name()) != index_no)
    7685              :     return NULL;
    7686              : 
    7687              :   // Match the body, a single call statement delete(m, k).
    7688          629 :   const std::vector<Statement*>* statements = this->statements_->statements();
    7689          629 :   if (statements->size() != 1)
    7690              :     return NULL;
    7691         2123 :   Expression_statement* es = statements->at(0)->expression_statement();
    7692           89 :   if (es == NULL)
    7693              :     return NULL;
    7694           89 :   Call_expression* call = es->expr()->call_expression();
    7695           89 :   if (call == NULL || !call->is_builtin()
    7696           40 :       || call->builtin_call_expression()->code()
    7697              :          != Builtin_call_expression::BUILTIN_DELETE)
    7698           49 :     return NULL;
    7699           40 :   if (!Expression::is_same_variable(call->args()->at(0), orig_range_expr)
    7700           40 :       || !Expression::is_same_variable(call->args()->at(1), this->index_var_))
    7701            7 :     return NULL;
    7702              : 
    7703              :   // Everything matches. Rewrite to mapclear(TYPE, MAP).
    7704           33 :   Expression* e1 = Expression::make_type_descriptor(map_type, loc);
    7705           33 :   Expression* e2 = this->make_range_ref(range_object, range_temp, loc);
    7706           33 :   call = Runtime::make_call(gogo, Runtime::MAPCLEAR, loc, 2, e1, e2);
    7707           33 :   Statement* s = Statement::make_statement(call, true);
    7708           33 :   s->determine_types(gogo);
    7709           33 :   return s;
    7710              : }
    7711              : 
    7712              : // Match
    7713              : //
    7714              : //   for i := range a { a[i] = zero }
    7715              : //
    7716              : // Lower it to call memclr on match, and return the statement.  Return
    7717              : // NULL otherwise.
    7718              : 
    7719              : Statement*
    7720        31648 : For_range_statement::lower_array_range_clear(Gogo* gogo,
    7721              :                                              Type* array_type,
    7722              :                                              Expression* orig_range_expr,
    7723              :                                              Block* temp_block,
    7724              :                                              Named_object* range_object,
    7725              :                                              Temporary_statement* range_temp,
    7726              :                                              Location loc)
    7727              : {
    7728        31648 :   if (this->value_var_ != NULL)
    7729              :     return NULL;
    7730        11354 :   if (this->index_var_ == NULL)
    7731              :     return NULL;
    7732              : 
    7733              :   // Match the body, a single assignment statement a[i] = zero.
    7734        11330 :   const std::vector<Statement*>* statements = this->statements_->statements();
    7735        11330 :   if (statements->size() != 1)
    7736              :     return NULL;
    7737         7844 :   Assignment_statement* as = statements->at(0)->assignment_statement();
    7738         1190 :   if (as == NULL || !as->rhs()->is_zero_value())
    7739         7461 :     return NULL;
    7740          385 :   if (as->lhs()->type()->interface_type() != NULL
    7741            4 :       && as->rhs()->type()->interface_type() == NULL
    7742            2 :       && !as->rhs()->type()->is_nil_type())
    7743              :     // Implicit type conversion may change a zero value to non-zero, like
    7744              :     // interface{}(0).
    7745              :     return NULL;
    7746          381 :   Array_index_expression* aie = as->lhs()->array_index_expression();
    7747          373 :   if (aie == NULL || aie->end() != NULL
    7748          373 :       || !Expression::is_same_variable(orig_range_expr, aie->array())
    7749          282 :       || !Expression::is_same_variable(this->index_var_, aie->start()))
    7750          100 :     return NULL;
    7751              : 
    7752              :   // Everything matches. Rewrite to
    7753              :   //
    7754              :   //   if len(a) != 0 {
    7755              :   //     tmp1 = &a[0]
    7756              :   //     tmp2 = len(a)*sizeof(elem(a))
    7757              :   //     memclr{NoHeap,Has}Pointers(tmp1, tmp2)
    7758              :   //     i = len(a) - 1
    7759              :   //   }
    7760              : 
    7761          562 :   Type* elem_type = array_type->array_type()->element_type();
    7762          281 :   int64_t elme_sz;
    7763          281 :   bool ok = elem_type->backend_type_size(gogo, &elme_sz);
    7764          281 :   if (!ok)
    7765              :     return NULL;
    7766              : 
    7767          281 :   Block* b = new Block(temp_block, loc);
    7768              : 
    7769          281 :   Expression* ref;
    7770          281 :   if (range_object == NULL && range_temp == NULL)
    7771              :     // is_same_variable implies no side effect, so it is ok to copy.
    7772           91 :     ref = orig_range_expr->copy();
    7773              :   else
    7774          190 :     ref = this->make_range_ref(range_object, range_temp, loc);
    7775          281 :   Expression* len = this->call_builtin(gogo, "len", ref, loc);
    7776          281 :   Temporary_statement* tslen = Statement::make_temporary(NULL, len, loc);
    7777          281 :   tslen->determine_types(gogo);
    7778          281 :   temp_block->add_statement(tslen);
    7779              : 
    7780          281 :   Expression* zero = Expression::make_integer_ul(0, this->index_var_->type(), loc);
    7781          281 :   ref = ref->copy();
    7782          281 :   Expression* elem = Expression::make_array_index(ref, zero, NULL, NULL, loc);
    7783          281 :   elem->array_index_expression()->set_needs_bounds_check(false);
    7784          281 :   Expression* e1 = Expression::make_unary(OPERATOR_AND, elem, loc);
    7785          281 :   Temporary_statement* ts1 = Statement::make_temporary(NULL, e1, loc);
    7786          281 :   ts1->determine_types(gogo);
    7787          281 :   b->add_statement(ts1);
    7788              : 
    7789          281 :   len = Expression::make_temporary_reference(tslen, loc);
    7790          281 :   Expression* sz = Expression::make_integer_int64(elme_sz, len->type(), loc);
    7791          281 :   Expression* e2 = Expression::make_binary(OPERATOR_MULT, len, sz, loc);
    7792          281 :   Temporary_statement* ts2 = Statement::make_temporary(NULL, e2, loc);
    7793          281 :   ts2->determine_types(gogo);
    7794          281 :   b->add_statement(ts2);
    7795              : 
    7796          281 :   Expression* ptr_arg = Expression::make_temporary_reference(ts1, loc);
    7797          281 :   Expression* sz_arg = Expression::make_temporary_reference(ts2, loc);
    7798          281 :   Expression* call;
    7799          281 :   if (elem_type->has_pointer())
    7800           30 :     call = Runtime::make_call(gogo, Runtime::MEMCLRHASPTR, loc, 2,
    7801              :                               ptr_arg, sz_arg);
    7802              :   else
    7803              :     {
    7804          251 :       Type* int32_type = Type::lookup_integer_type("int32");
    7805          251 :       Expression* zero32 = Expression::make_integer_ul(0, int32_type, loc);
    7806          251 :       call = Runtime::make_call(gogo, Runtime::BUILTIN_MEMSET, loc, 3, ptr_arg,
    7807              :                                 zero32, sz_arg);
    7808              :     }
    7809          281 :   Statement* cs3 = Statement::make_statement(call, true);
    7810          281 :   cs3->determine_types(gogo);
    7811          281 :   b->add_statement(cs3);
    7812              : 
    7813          281 :   len = Expression::make_temporary_reference(tslen, loc);
    7814          281 :   Expression* one = Expression::make_integer_ul(1, len->type(), loc);
    7815          281 :   Expression* rhs = Expression::make_binary(OPERATOR_MINUS, len, one, loc);
    7816          281 :   Expression* lhs = this->index_var_->copy();
    7817          281 :   Statement* as4 = Statement::make_assignment(lhs, rhs, loc);
    7818          281 :   as4->determine_types(gogo);
    7819          281 :   b->add_statement(as4);
    7820              : 
    7821          281 :   len = Expression::make_temporary_reference(tslen, loc);
    7822          281 :   zero = zero->copy();
    7823          281 :   Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, len, zero, loc);
    7824          281 :   Statement* ret = Statement::make_if_statement(cond, b, NULL, loc);
    7825          281 :   ret->determine_types(gogo);
    7826          281 :   return ret;
    7827              : }
    7828              : 
    7829              : // Return the break LABEL_EXPR.
    7830              : 
    7831              : Unnamed_label*
    7832         1527 : For_range_statement::break_label()
    7833              : {
    7834         1527 :   if (this->break_label_ == NULL)
    7835         1414 :     this->break_label_ = new Unnamed_label(this->location());
    7836         1527 :   return this->break_label_;
    7837              : }
    7838              : 
    7839              : // Return the continue LABEL_EXPR.
    7840              : 
    7841              : Unnamed_label*
    7842         5908 : For_range_statement::continue_label()
    7843              : {
    7844         5908 :   if (this->continue_label_ == NULL)
    7845         3563 :     this->continue_label_ = new Unnamed_label(this->location());
    7846         5908 :   return this->continue_label_;
    7847              : }
    7848              : 
    7849              : // Dump the AST representation for a for range statement.
    7850              : 
    7851              : void
    7852            0 : For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
    7853              : {
    7854              : 
    7855            0 :   ast_dump_context->print_indent();
    7856            0 :   ast_dump_context->ostream() << "for ";
    7857            0 :   ast_dump_context->dump_expression(this->index_var_);
    7858            0 :   if (this->value_var_ != NULL)
    7859              :     {
    7860            0 :       ast_dump_context->ostream() << ", ";
    7861            0 :       ast_dump_context->dump_expression(this->value_var_);
    7862              :     }
    7863              : 
    7864            0 :   ast_dump_context->ostream() << " = range ";
    7865            0 :   ast_dump_context->dump_expression(this->range_);
    7866            0 :   if (ast_dump_context->dump_subblocks())
    7867              :     {
    7868            0 :       ast_dump_context->ostream() << " {" << std::endl;
    7869              : 
    7870            0 :       ast_dump_context->indent();
    7871              : 
    7872            0 :       ast_dump_context->dump_block(this->statements_);
    7873              : 
    7874            0 :       ast_dump_context->unindent();
    7875            0 :       ast_dump_context->print_indent();
    7876            0 :       ast_dump_context->ostream() << "}";
    7877              :     }
    7878            0 :   ast_dump_context->ostream() << dsuffix(location()) << std::endl;
    7879            0 : }
    7880              : 
    7881              : // Make a for statement with a range clause.
    7882              : 
    7883              : For_range_statement*
    7884        34430 : Statement::make_for_range_statement(Expression* index_var,
    7885              :                                     Expression* value_var,
    7886              :                                     Expression* range,
    7887              :                                     Location location)
    7888              : {
    7889        34430 :   return new For_range_statement(index_var, value_var, range, location);
    7890              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.