From patchwork Fri Jul 18 21:59:14 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 371728 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id D5CBD140119 for ; Sat, 19 Jul 2014 07:59:35 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=Iy7Cn9xyjuDvTCa5VhSvfESwL0O4o3yo67i09Zdrgq6RcvLL2JyLs pxIojHHKM985Y5Coa1l9tvVhhzOVzfHRP44MORJBglTicDv2Tzc9Omx43GGKDMzR jBTfBMYBJOrkls3v4w4l0PlEOcm7Yn7tiUtok9QDsoJ5KWV3ZR7ZtY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; s= default; bh=/uRBYpm+9HZkdXd93SRQ6CVb5K4=; b=y7t4xNmd7/+aNBx7HXWW HnZWrI3olTUWBzdo0bHa7EdMLXEo5Tb0axBrhHf5SSetGTdtyvvJn+ZaXBP4WI2l ui5bg0VJlG4tTTh7bt1HAvv7sGr/wa51d/QwQ/j/gp+A6R6KuUTuwsh8vP1siThl AynP78j+Qpvrz37Z2w2N5JY= Received: (qmail 4237 invoked by alias); 18 Jul 2014 21:59:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 4154 invoked by uid 89); 18 Jul 2014 21:59:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS, T_TVD_MIME_NO_HEADERS autolearn=ham version=3.3.2 X-HELO: mail-wg0-f51.google.com Received: from mail-wg0-f51.google.com (HELO mail-wg0-f51.google.com) (74.125.82.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Fri, 18 Jul 2014 21:59:22 +0000 Received: by mail-wg0-f51.google.com with SMTP id b13so4097864wgh.22 for ; Fri, 18 Jul 2014 14:59:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:user-agent :mime-version:content-type; bh=UU/ooJN79gzBY3XWRMViLnG6NPk+i27nkzFitvRo4sI=; b=DxLSBXjfqVDXMQaUKOJ4JcUYnpujQ5JkZuckv/d/pUV5n9EinL0qG3QdNN1lx/0CVO Hn3VdyadKL9uOQnFCu0/sV80Z63kqf8ydArQQonoxKExnFrM3PzG6QQxO39MDgSe9lAN VICIKuME6jcOTouBroxnuCwRXlnxJI6epSaoHjIu8kmRqYkKljSMuuzapiM16niXWKUe IiMWO8AK8r5loilyYwqMFZrZsz93ZKIlXar4eSyr1B+lYzxoBUZRPAUxgJJWW9Pz0+DV 2q3C4Ww97mqzVMtH6naQt2MeT46S37susUzjtr+vI3rBmClqC4WbKKAlHEdE+UVmXEfu VoDQ== X-Gm-Message-State: ALoCoQlOK2Cb3Ud8qHfdKRl+iRc0PZ21xEMs5ofBxe5S3U1GjR0vRqtey8dDBuCo77jw9/NNvSRJ X-Received: by 10.194.86.225 with SMTP id s1mr166453wjz.21.1405720758753; Fri, 18 Jul 2014 14:59:18 -0700 (PDT) Received: from iant-glaptop.roam.corp.google.com.google.com ([172.16.38.87]) by mx.google.com with ESMTPSA id ch5sm17168202wjb.18.2014.07.18.14.59.15 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 18 Jul 2014 14:59:17 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Check for mismatch between results and uses Date: Fri, 18 Jul 2014 14:59:14 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) MIME-Version: 1.0 X-IsSubscribed: yes The Go frontend had a bug in that it would not give an error for a, b := F() when F returned more than two results. This patch fixes the bug. I've proposed a test case for the master testsuite in http://codereview.appspot.com/111360045 . Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian diff -r d56f774d848e go/expressions.cc --- a/go/expressions.cc Fri Jul 11 16:53:55 2014 -0700 +++ b/go/expressions.cc Fri Jul 18 14:15:40 2014 -0700 @@ -9065,6 +9065,15 @@ return (*this->results_)[i]; } +// Set the number of results expected from a call expression. + +void +Call_expression::set_expected_result_count(size_t count) +{ + go_assert(this->expected_result_count_ == 0); + this->expected_result_count_ = count; +} + // Return whether this is a call to the predeclared function recover. bool @@ -9252,6 +9261,15 @@ return; } + if (this->expected_result_count_ != 0 + && this->expected_result_count_ != this->result_count()) + { + if (this->issue_error()) + this->report_error(_("function result count mismatch")); + this->set_is_error(); + return; + } + bool is_method = fntype->is_method(); if (is_method) { @@ -9302,6 +9320,20 @@ if (!is_method || this->args_->size() > 1) this->report_error(_("too many arguments")); } + else if (this->args_->size() == 1 + && this->args_->front()->call_expression() != NULL + && this->args_->front()->call_expression()->result_count() > 1) + { + // This is F(G()) when G returns more than one result. If the + // results can be matched to parameters, it would have been + // lowered in do_lower. If we get here we know there is a + // mismatch. + if (this->args_->front()->call_expression()->result_count() + < parameters->size()) + this->report_error(_("not enough arguments")); + else + this->report_error(_("too many arguments")); + } else { int i = 0; diff -r d56f774d848e go/expressions.h --- a/go/expressions.h Fri Jul 11 16:53:55 2014 -0700 +++ b/go/expressions.h Fri Jul 18 14:15:40 2014 -0700 @@ -1606,9 +1606,9 @@ Location location) : Expression(EXPRESSION_CALL, location), fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL), - call_temp_(NULL), is_varargs_(is_varargs), are_hidden_fields_ok_(false), - varargs_are_lowered_(false), types_are_determined_(false), - is_deferred_(false), issued_error_(false) + call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs), + are_hidden_fields_ok_(false), varargs_are_lowered_(false), + types_are_determined_(false), is_deferred_(false), issued_error_(false) { } // The function to call. @@ -1639,6 +1639,12 @@ Temporary_statement* result(size_t i) const; + // Set the number of results expected from this call. This is used + // when the call appears in a context that expects multiple results, + // such as a, b = f(). + void + set_expected_result_count(size_t); + // Return whether this is a call to the predeclared function // recover. bool @@ -1767,6 +1773,9 @@ Bexpression* call_; // A temporary variable to store this call if the function returns a tuple. Temporary_statement* call_temp_; + // If not 0, the number of results expected from this call, when + // used in a context that expects multiple values. + size_t expected_result_count_; // True if the last argument is a varargs argument (f(a...)). bool is_varargs_; // True if this statement may pass hidden fields in the arguments. diff -r d56f774d848e go/parse.cc --- a/go/parse.cc Fri Jul 11 16:53:55 2014 -0700 +++ b/go/parse.cc Fri Jul 18 14:15:40 2014 -0700 @@ -1694,6 +1694,8 @@ // the right number of values, but it might. Declare the variables, // and then assign the results of the call to them. + call->set_expected_result_count(vars->size()); + Named_object* first_var = NULL; unsigned int index = 0; bool any_new = false; @@ -4101,6 +4103,7 @@ { if (op != OPERATOR_EQ) error_at(location, "multiple results only permitted with %<=%>"); + call->set_expected_result_count(lhs->size()); delete vals; vals = new Expression_list; for (unsigned int i = 0; i < lhs->size(); ++i) diff -r d56f774d848e go/statements.cc --- a/go/statements.cc Fri Jul 11 16:53:55 2014 -0700 +++ b/go/statements.cc Fri Jul 18 14:15:40 2014 -0700 @@ -2664,6 +2664,7 @@ && vals->front()->call_expression() != NULL) { Call_expression* call = vals->front()->call_expression(); + call->set_expected_result_count(results_count); delete vals; vals = new Expression_list; for (size_t i = 0; i < results_count; ++i)