From patchwork Wed Jan 19 16:55:27 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 79495 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]) by ozlabs.org (Postfix) with SMTP id 94895B70EF for ; Thu, 20 Jan 2011 03:55:44 +1100 (EST) Received: (qmail 7197 invoked by alias); 19 Jan 2011 16:55:43 -0000 Received: (qmail 7189 invoked by uid 22791); 19 Jan 2011 16:55:42 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 19 Jan 2011 16:55:33 +0000 Received: from kpbe17.cbf.corp.google.com (kpbe17.cbf.corp.google.com [172.25.105.81]) by smtp-out.google.com with ESMTP id p0JGtVgc002158 for ; Wed, 19 Jan 2011 08:55:31 -0800 Received: from pxi11 (pxi11.prod.google.com [10.243.27.11]) by kpbe17.cbf.corp.google.com with ESMTP id p0JGtUMw012708 (version=TLSv1/SSLv3 cipher=RC4-MD5 bits=128 verify=NOT) for ; Wed, 19 Jan 2011 08:55:30 -0800 Received: by pxi11 with SMTP id 11so212938pxi.35 for ; Wed, 19 Jan 2011 08:55:29 -0800 (PST) Received: by 10.142.131.20 with SMTP id e20mr901977wfd.309.1295456129825; Wed, 19 Jan 2011 08:55:29 -0800 (PST) Received: from coign.google.com (dhcp-172-22-125-210.mtv.corp.google.com [172.22.125.210]) by mx.google.com with ESMTPS id x35sm9815675wfd.13.2011.01.19.08.55.28 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 19 Jan 2011 08:55:29 -0800 (PST) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: Go patch committed: Improve check for const initializer loop Date: Wed, 19 Jan 2011 08:55:27 -0800 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true X-IsSubscribed: yes 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 This patch to the Go frontend improves the check for loops in const initializers. This avoids crashes when two consts refer to each other. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. Ian diff -r e32592b8f83f go/expressions.cc --- a/go/expressions.cc Wed Jan 19 08:03:04 2011 -0800 +++ b/go/expressions.cc Wed Jan 19 08:48:54 2011 -0800 @@ -2348,6 +2348,10 @@ name() const { return this->constant_->name(); } + // Check that the initializer does not refer to the constant itself. + void + check_for_init_loop(); + protected: Expression* do_lower(Gogo*, Named_object*, int); @@ -2610,24 +2614,50 @@ } } -// Check types of a const reference. +// Check for a loop in which the initializer of a constant refers to +// the constant itself. void -Const_expression::do_check_types(Gogo*) +Const_expression::check_for_init_loop() { if (this->type_ != NULL && this->type_->is_error_type()) return; - Expression* init = this->constant_->const_value()->expr(); - Find_named_object find_named_object(this->constant_); - Expression::traverse(&init, &find_named_object); - if (find_named_object.found()) + if (this->seen_) { this->report_error(_("constant refers to itself")); this->type_ = Type::make_error_type(); return; } + Expression* init = this->constant_->const_value()->expr(); + Find_named_object find_named_object(this->constant_); + + this->seen_ = true; + Expression::traverse(&init, &find_named_object); + this->seen_ = false; + + if (find_named_object.found()) + { + if (this->type_ == NULL || !this->type_->is_error_type()) + { + this->report_error(_("constant refers to itself")); + this->type_ = Type::make_error_type(); + } + return; + } +} + +// Check types of a const reference. + +void +Const_expression::do_check_types(Gogo*) +{ + if (this->type_ != NULL && this->type_->is_error_type()) + return; + + this->check_for_init_loop(); + if (this->type_ == NULL || this->type_->is_abstract()) return; @@ -2754,9 +2784,19 @@ switch ((*pexpr)->classification()) { case Expression::EXPRESSION_CONST_REFERENCE: - if (static_cast(*pexpr)->named_object() == this->no_) - break; - return TRAVERSE_CONTINUE; + { + Const_expression* ce = static_cast(*pexpr); + if (ce->named_object() == this->no_) + break; + + // We need to check a constant initializer explicitly, as + // loops here will not be caught by the loop checking for + // variable initializers. + ce->check_for_init_loop(); + + return TRAVERSE_CONTINUE; + } + case Expression::EXPRESSION_VAR_REFERENCE: if ((*pexpr)->var_expression()->named_object() == this->no_) break;