From patchwork Mon Oct 23 21:16:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 157111 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce89:0:b0:403:3b70:6f57 with SMTP id p9csp1558806vqx; Mon, 23 Oct 2023 14:17:33 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHuhoGYJOnzrITYejRsskU/AKuVfcBh2iAQtvQFps65vRXUeYQn3ALoW7yDCPDnRGLJWCxg X-Received: by 2002:ad4:5be5:0:b0:66c:fae1:1c72 with SMTP id k5-20020ad45be5000000b0066cfae11c72mr12833978qvc.42.1698095853042; Mon, 23 Oct 2023 14:17:33 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1698095853; cv=pass; d=google.com; s=arc-20160816; b=rkcO45q4CRWqAaCkqK221GKuiRNKHnfa7Ht7UDRo0og4TMOclSpwvkH7R+jr7Qz4pL 215MKnKRRvwPt0T/W5PciHGW4jtPzbMa1MtCbgDVJvROAxDDFc8lKKL5mo9Re7zTuCOb 2+yuxwIGqd0mjVFlIAVNYpriqFtY+vGG+8+8xj/0DaW1ZIrkeGZZMzDj1rvVBGeg76p5 p5GFy2GOQDM452Et+sCMZuUZelFYV8LBVklVirHKDa95DzhDkXqitdKH+2eFJQfHPw0J N7CwB9XQgU70nKv+eHMsjyAOf7YlgoVbfhBEhwXB4DAE+y8TusZyEkTGneip3ErxQoHx NToA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:to:subject:message-id:date:from :mime-version:dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=qqgUwgYLfjueeIgeYLO41e40pTIuoitnSMIQDRyRbWo=; fh=sx1AF6BoRLLvWrm7PiL2RBt/kekZxFGoFwZKL1Ho560=; b=h0HKUnqo3nQkQeASXW5XixmASRValwKUzcff9lO68vwLmg02I1d33vzscY+69PDG9W ujzXAGkvN7BL8ShP9AmgPl/i6zBl0wPbb0FjaMJGkAYlRByQxdxwyzeqeVC3g0j0i+LY XixeOpUjw1Fxt7TdzNWrb7XGybRTAUkEyc74P+K2ShvcK8W4dHfyN9H3K/TH3nIA1/Wt VJkRevzzN6tRDQZQM5f2Y7tQTn6a76o0iicvJU0zQY0yC4RE6luD11u7HchHfzbBcK4F 83O+0Mzgg6q2FJg7K8JHknN4du6ISghyasMCWrEaWI27INwthGoYdguSssXKc+2jNtDx spFw== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@golang-org.20230601.gappssmtp.com header.s=20230601 header.b=tCeXSqaT; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=golang.org Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id o2-20020a05620a130200b0077567044451si5658038qkj.152.2023.10.23.14.17.32 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Oct 2023 14:17:33 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@golang-org.20230601.gappssmtp.com header.s=20230601 header.b=tCeXSqaT; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=golang.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C6A9C3850867 for ; Mon, 23 Oct 2023 21:17:32 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-yw1-x112e.google.com (mail-yw1-x112e.google.com [IPv6:2607:f8b0:4864:20::112e]) by sourceware.org (Postfix) with ESMTPS id BBF5A386076C for ; Mon, 23 Oct 2023 21:17:05 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BBF5A386076C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=golang.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=golang.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BBF5A386076C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::112e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698095828; cv=none; b=saeRMwpRmLtxTmRBRVUx6tGw8HJcg02KF69fWfsMWcfVXkOHruC+Fwqbyber356Cm/RXh1tSNN0R1bfnxjsWU9uYQ5h7njTso+7Xb6XWCDEgEcNPRw7z7ql9EKDrdUXQsR0wvcc5POUj1S/EMBuT7mksEyUsz3LudVfk9dkZocU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698095828; c=relaxed/simple; bh=LuZAz8MBhROeYFuSG6fGqLwv75yD5Eua4Tr2g+bZpFg=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=Nj95LgkMTTteTniQt/TPP01KgmTJKsrZe8+sRzwujJneiEJdRAvSqOggzB80kCDeBmPGr7gJ1WXd0hANhjkV/haerKtOnec8KaYSbq+mlSpLyBmJas8uwMJtDI9LBemFwOGoasafkXNosvFVIxZ/RVNMTxJrCkGaDkbEVx1UTLQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-yw1-x112e.google.com with SMTP id 00721157ae682-5a7c011e113so41310577b3.1 for ; Mon, 23 Oct 2023 14:17:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=golang-org.20230601.gappssmtp.com; s=20230601; t=1698095825; x=1698700625; darn=gcc.gnu.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=qqgUwgYLfjueeIgeYLO41e40pTIuoitnSMIQDRyRbWo=; b=tCeXSqaTD6q9lUaa/Ur6BP90oWawlnpW/twEj+w97zsF+E7Wf/aHps83WUPnc7lDfQ Ts/9YmCDRvGwceBjl11AmcdjVgbQf+yPOdDTxP1GDym0Fkm96POqgnlG7FE+cQllDxvZ fZ65q8/M1VARKNi/rAPbz2WcrZmy+Qr6aiR/myIJ2kPdkil60WTCs3v3QwLzFskM4TEv 6UctH5WIlsMGLlgROPszUIEK347W9w4OYRsRXByKB71DcG+YCDgUaAV+vHz+fQepHcdX eDAVT8cILpC/97umgKlaB0sULeL/kChNajan1ClzTWRt4ujUgICTZZyGi15FeYmrAeqv jb8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698095825; x=1698700625; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=qqgUwgYLfjueeIgeYLO41e40pTIuoitnSMIQDRyRbWo=; b=anXhUuYCtaGoC4uxnm4J/FXHk2LV2f3ZtuFN8eD3At3NLN/EbEG2VYTrTEAdngdNuY ndIKq7FQGto+xq6Htw9ucb9HhW7oudFF1XC7p9Vvdy84PKkjpGx8Kk5NH5b1Ssy21/HZ Nu1xsUAdac6OmVdHNHpOFW1guPFgL4JUsa9l0YMIBrHZB+hOYwtgE5L8QKnEEGghJn/i ZlueP2c6qPkJ4f88ADv9oAXQF5dS/j/CT3+f7P4hsi3cggU6dGsiHtx3oeYk8bZryjz2 IH6NkHlvEkJiG4mkkB7fNZFkJ4VCB/LInDNqZewK+EFXsGvWrN3qTu+1l6Nu0mV1Jvm0 lSxw== X-Gm-Message-State: AOJu0YzoRnmAu1eBg8UIyCl7AY/1406nHI8VLt8MEKGUCwx4qyqO5dBD X6rRYQyvr9quym0jtpBefw77/g8FOqfI2GO06fMZnnS706iNi1dbDVs= X-Received: by 2002:a0d:cc4d:0:b0:5a7:d4c2:d59e with SMTP id o74-20020a0dcc4d000000b005a7d4c2d59emr12502315ywd.22.1698095825018; Mon, 23 Oct 2023 14:17:05 -0700 (PDT) MIME-Version: 1.0 From: Ian Lance Taylor Date: Mon, 23 Oct 2023 14:16:53 -0700 Message-ID: Subject: Go patch committed: Move Selector_expression up in file To: gcc-patches , gofrontend-dev X-Spam-Status: No, score=-10.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_FILL_THIS_FORM_SHORT autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780582557190319930 X-GMAIL-MSGID: 1780582557190319930 This patch to the Go frontend just moves Selector_expression up in file. This is a mechanical change to expressions.cc. This will make Selector_expression visible to Builtin_call_expression for later work. This produces a very large "git --diff", but "git diff --minimal" is clear. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline. Ian 02aa322c8cfd3f60fa5a3a0eee4340bb644261fe diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 35b9cd780da..aff74bd74dc 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -3c2a441ef6cafb018bb3cc16f8403ae3d1daf2e1 +e997b0201512110e9c20b1fdfd40014830031047 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index f218731041b..c9177b71174 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -8426,6 +8426,287 @@ Expression::make_bound_method(Expression* expr, const Method* method, return new Bound_method_expression(expr, method, function, location); } +// A general selector. This is a Parser_expression for LEFT.NAME. It +// is lowered after we know the type of the left hand side. + +class Selector_expression : public Parser_expression +{ + public: + Selector_expression(Expression* left, const std::string& name, + Location location) + : Parser_expression(EXPRESSION_SELECTOR, location), + left_(left), name_(name) + { } + + protected: + int + do_traverse(Traverse* traverse) + { return Expression::traverse(&this->left_, traverse); } + + Expression* + do_lower(Gogo*, Named_object*, Statement_inserter*, int); + + Expression* + do_copy() + { + return new Selector_expression(this->left_->copy(), this->name_, + this->location()); + } + + void + do_dump_expression(Ast_dump_context* ast_dump_context) const; + + private: + Expression* + lower_method_expression(Gogo*); + + // The expression on the left hand side. + Expression* left_; + // The name on the right hand side. + std::string name_; +}; + +// Lower a selector expression once we know the real type of the left +// hand side. + +Expression* +Selector_expression::do_lower(Gogo* gogo, Named_object*, Statement_inserter*, + int) +{ + Expression* left = this->left_; + if (left->is_type_expression()) + return this->lower_method_expression(gogo); + return Type::bind_field_or_method(gogo, left->type(), left, this->name_, + this->location()); +} + +// Lower a method expression T.M or (*T).M. We turn this into a +// function literal. + +Expression* +Selector_expression::lower_method_expression(Gogo* gogo) +{ + Location location = this->location(); + Type* left_type = this->left_->type(); + Type* type = left_type; + const std::string& name(this->name_); + + bool is_pointer; + if (type->points_to() == NULL) + is_pointer = false; + else + { + is_pointer = true; + type = type->points_to(); + } + + Named_type* nt = type->named_type(); + Struct_type* st = type->struct_type(); + bool is_ambiguous; + Method* method = NULL; + if (nt != NULL) + method = nt->method_function(name, &is_ambiguous); + else if (st != NULL) + method = st->method_function(name, &is_ambiguous); + const Typed_identifier* imethod = NULL; + if (method == NULL && !is_pointer) + { + Interface_type* it = type->interface_type(); + if (it != NULL) + imethod = it->find_method(name); + } + + if ((method == NULL && imethod == NULL) + || (left_type->named_type() != NULL && left_type->points_to() != NULL)) + { + if (nt != NULL) + { + if (!is_ambiguous) + go_error_at(location, "type %<%s%s%> has no method %<%s%>", + is_pointer ? "*" : "", + nt->message_name().c_str(), + Gogo::message_name(name).c_str()); + else + go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>", + Gogo::message_name(name).c_str(), + is_pointer ? "*" : "", + nt->message_name().c_str()); + } + else + { + if (!is_ambiguous) + go_error_at(location, "type has no method %<%s%>", + Gogo::message_name(name).c_str()); + else + go_error_at(location, "method %<%s%> is ambiguous", + Gogo::message_name(name).c_str()); + } + return Expression::make_error(location); + } + + if (method != NULL && !is_pointer && !method->is_value_method()) + { + go_error_at(location, "method requires pointer (use %<(*%s).%s%>)", + nt->message_name().c_str(), + Gogo::message_name(name).c_str()); + return Expression::make_error(location); + } + + // Build a new function type in which the receiver becomes the first + // argument. + Function_type* method_type; + if (method != NULL) + { + method_type = method->type(); + go_assert(method_type->is_method()); + } + else + { + method_type = imethod->type()->function_type(); + go_assert(method_type != NULL && !method_type->is_method()); + } + + const char* const receiver_name = "$this"; + Typed_identifier_list* parameters = new Typed_identifier_list(); + parameters->push_back(Typed_identifier(receiver_name, this->left_->type(), + location)); + + const Typed_identifier_list* method_parameters = method_type->parameters(); + if (method_parameters != NULL) + { + int i = 0; + for (Typed_identifier_list::const_iterator p = method_parameters->begin(); + p != method_parameters->end(); + ++p, ++i) + { + if (!p->name().empty() && !Gogo::is_sink_name(p->name())) + parameters->push_back(*p); + else + { + char buf[20]; + snprintf(buf, sizeof buf, "$param%d", i); + parameters->push_back(Typed_identifier(buf, p->type(), + p->location())); + } + } + } + + const Typed_identifier_list* method_results = method_type->results(); + Typed_identifier_list* results; + if (method_results == NULL) + results = NULL; + else + { + results = new Typed_identifier_list(); + for (Typed_identifier_list::const_iterator p = method_results->begin(); + p != method_results->end(); + ++p) + results->push_back(*p); + } + + Function_type* fntype = Type::make_function_type(NULL, parameters, results, + location); + if (method_type->is_varargs()) + fntype->set_is_varargs(); + + // We generate methods which always takes a pointer to the receiver + // as their first argument. If this is for a pointer type, we can + // simply reuse the existing function. We use an internal hack to + // get the right type. + // FIXME: This optimization is disabled because it doesn't yet work + // with function descriptors when the method expression is not + // directly called. + if (method != NULL && is_pointer && false) + { + Named_object* mno = (method->needs_stub_method() + ? method->stub_object() + : method->named_object()); + Expression* f = Expression::make_func_reference(mno, NULL, location); + f = Expression::make_cast(fntype, f, location); + Type_conversion_expression* tce = + static_cast(f); + tce->set_may_convert_function_types(); + return f; + } + + Named_object* no = gogo->start_function(gogo->thunk_name(), fntype, false, + location); + + Named_object* vno = gogo->lookup(receiver_name, NULL); + go_assert(vno != NULL); + Expression* ve = Expression::make_var_reference(vno, location); + Expression* bm; + if (method != NULL) + bm = Type::bind_field_or_method(gogo, type, ve, name, location); + else + bm = Expression::make_interface_field_reference(ve, name, location); + + // Even though we found the method above, if it has an error type we + // may see an error here. + if (bm->is_error_expression()) + { + gogo->finish_function(location); + return bm; + } + + Expression_list* args; + if (parameters->size() <= 1) + args = NULL; + else + { + args = new Expression_list(); + Typed_identifier_list::const_iterator p = parameters->begin(); + ++p; + for (; p != parameters->end(); ++p) + { + vno = gogo->lookup(p->name(), NULL); + go_assert(vno != NULL); + args->push_back(Expression::make_var_reference(vno, location)); + } + } + + gogo->start_block(location); + + Call_expression* call = Expression::make_call(bm, args, + method_type->is_varargs(), + location); + + Statement* s = Statement::make_return_from_call(call, location); + gogo->add_statement(s); + + Block* b = gogo->finish_block(location); + + gogo->add_block(b, location); + + // Lower the call in case there are multiple results. + gogo->lower_block(no, b); + gogo->flatten_block(no, b); + + gogo->finish_function(location); + + return Expression::make_func_reference(no, NULL, location); +} + +// Dump the ast for a selector expression. + +void +Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context) + const +{ + ast_dump_context->dump_expression(this->left_); + ast_dump_context->ostream() << "."; + ast_dump_context->ostream() << this->name_; +} + +// Make a selector expression. + +Expression* +Expression::make_selector(Expression* left, const std::string& name, + Location location) +{ + return new Selector_expression(left, name, location); +} + // Class Builtin_call_expression. This is used for a call to a // builtin function. @@ -15265,287 +15546,6 @@ Expression::make_interface_field_reference(Expression* expr, return new Interface_field_reference_expression(expr, field, location); } -// A general selector. This is a Parser_expression for LEFT.NAME. It -// is lowered after we know the type of the left hand side. - -class Selector_expression : public Parser_expression -{ - public: - Selector_expression(Expression* left, const std::string& name, - Location location) - : Parser_expression(EXPRESSION_SELECTOR, location), - left_(left), name_(name) - { } - - protected: - int - do_traverse(Traverse* traverse) - { return Expression::traverse(&this->left_, traverse); } - - Expression* - do_lower(Gogo*, Named_object*, Statement_inserter*, int); - - Expression* - do_copy() - { - return new Selector_expression(this->left_->copy(), this->name_, - this->location()); - } - - void - do_dump_expression(Ast_dump_context* ast_dump_context) const; - - private: - Expression* - lower_method_expression(Gogo*); - - // The expression on the left hand side. - Expression* left_; - // The name on the right hand side. - std::string name_; -}; - -// Lower a selector expression once we know the real type of the left -// hand side. - -Expression* -Selector_expression::do_lower(Gogo* gogo, Named_object*, Statement_inserter*, - int) -{ - Expression* left = this->left_; - if (left->is_type_expression()) - return this->lower_method_expression(gogo); - return Type::bind_field_or_method(gogo, left->type(), left, this->name_, - this->location()); -} - -// Lower a method expression T.M or (*T).M. We turn this into a -// function literal. - -Expression* -Selector_expression::lower_method_expression(Gogo* gogo) -{ - Location location = this->location(); - Type* left_type = this->left_->type(); - Type* type = left_type; - const std::string& name(this->name_); - - bool is_pointer; - if (type->points_to() == NULL) - is_pointer = false; - else - { - is_pointer = true; - type = type->points_to(); - } - - Named_type* nt = type->named_type(); - Struct_type* st = type->struct_type(); - bool is_ambiguous; - Method* method = NULL; - if (nt != NULL) - method = nt->method_function(name, &is_ambiguous); - else if (st != NULL) - method = st->method_function(name, &is_ambiguous); - const Typed_identifier* imethod = NULL; - if (method == NULL && !is_pointer) - { - Interface_type* it = type->interface_type(); - if (it != NULL) - imethod = it->find_method(name); - } - - if ((method == NULL && imethod == NULL) - || (left_type->named_type() != NULL && left_type->points_to() != NULL)) - { - if (nt != NULL) - { - if (!is_ambiguous) - go_error_at(location, "type %<%s%s%> has no method %<%s%>", - is_pointer ? "*" : "", - nt->message_name().c_str(), - Gogo::message_name(name).c_str()); - else - go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>", - Gogo::message_name(name).c_str(), - is_pointer ? "*" : "", - nt->message_name().c_str()); - } - else - { - if (!is_ambiguous) - go_error_at(location, "type has no method %<%s%>", - Gogo::message_name(name).c_str()); - else - go_error_at(location, "method %<%s%> is ambiguous", - Gogo::message_name(name).c_str()); - } - return Expression::make_error(location); - } - - if (method != NULL && !is_pointer && !method->is_value_method()) - { - go_error_at(location, "method requires pointer (use %<(*%s).%s%>)", - nt->message_name().c_str(), - Gogo::message_name(name).c_str()); - return Expression::make_error(location); - } - - // Build a new function type in which the receiver becomes the first - // argument. - Function_type* method_type; - if (method != NULL) - { - method_type = method->type(); - go_assert(method_type->is_method()); - } - else - { - method_type = imethod->type()->function_type(); - go_assert(method_type != NULL && !method_type->is_method()); - } - - const char* const receiver_name = "$this"; - Typed_identifier_list* parameters = new Typed_identifier_list(); - parameters->push_back(Typed_identifier(receiver_name, this->left_->type(), - location)); - - const Typed_identifier_list* method_parameters = method_type->parameters(); - if (method_parameters != NULL) - { - int i = 0; - for (Typed_identifier_list::const_iterator p = method_parameters->begin(); - p != method_parameters->end(); - ++p, ++i) - { - if (!p->name().empty() && !Gogo::is_sink_name(p->name())) - parameters->push_back(*p); - else - { - char buf[20]; - snprintf(buf, sizeof buf, "$param%d", i); - parameters->push_back(Typed_identifier(buf, p->type(), - p->location())); - } - } - } - - const Typed_identifier_list* method_results = method_type->results(); - Typed_identifier_list* results; - if (method_results == NULL) - results = NULL; - else - { - results = new Typed_identifier_list(); - for (Typed_identifier_list::const_iterator p = method_results->begin(); - p != method_results->end(); - ++p) - results->push_back(*p); - } - - Function_type* fntype = Type::make_function_type(NULL, parameters, results, - location); - if (method_type->is_varargs()) - fntype->set_is_varargs(); - - // We generate methods which always takes a pointer to the receiver - // as their first argument. If this is for a pointer type, we can - // simply reuse the existing function. We use an internal hack to - // get the right type. - // FIXME: This optimization is disabled because it doesn't yet work - // with function descriptors when the method expression is not - // directly called. - if (method != NULL && is_pointer && false) - { - Named_object* mno = (method->needs_stub_method() - ? method->stub_object() - : method->named_object()); - Expression* f = Expression::make_func_reference(mno, NULL, location); - f = Expression::make_cast(fntype, f, location); - Type_conversion_expression* tce = - static_cast(f); - tce->set_may_convert_function_types(); - return f; - } - - Named_object* no = gogo->start_function(gogo->thunk_name(), fntype, false, - location); - - Named_object* vno = gogo->lookup(receiver_name, NULL); - go_assert(vno != NULL); - Expression* ve = Expression::make_var_reference(vno, location); - Expression* bm; - if (method != NULL) - bm = Type::bind_field_or_method(gogo, type, ve, name, location); - else - bm = Expression::make_interface_field_reference(ve, name, location); - - // Even though we found the method above, if it has an error type we - // may see an error here. - if (bm->is_error_expression()) - { - gogo->finish_function(location); - return bm; - } - - Expression_list* args; - if (parameters->size() <= 1) - args = NULL; - else - { - args = new Expression_list(); - Typed_identifier_list::const_iterator p = parameters->begin(); - ++p; - for (; p != parameters->end(); ++p) - { - vno = gogo->lookup(p->name(), NULL); - go_assert(vno != NULL); - args->push_back(Expression::make_var_reference(vno, location)); - } - } - - gogo->start_block(location); - - Call_expression* call = Expression::make_call(bm, args, - method_type->is_varargs(), - location); - - Statement* s = Statement::make_return_from_call(call, location); - gogo->add_statement(s); - - Block* b = gogo->finish_block(location); - - gogo->add_block(b, location); - - // Lower the call in case there are multiple results. - gogo->lower_block(no, b); - gogo->flatten_block(no, b); - - gogo->finish_function(location); - - return Expression::make_func_reference(no, NULL, location); -} - -// Dump the ast for a selector expression. - -void -Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context) - const -{ - ast_dump_context->dump_expression(this->left_); - ast_dump_context->ostream() << "."; - ast_dump_context->ostream() << this->name_; -} - -// Make a selector expression. - -Expression* -Expression::make_selector(Expression* left, const std::string& name, - Location location) -{ - return new Selector_expression(left, name, location); -} - // Class Allocation_expression. int