From: ian Date: Wed, 19 Jan 2011 16:55:24 +0000 (+0000) Subject: Improve check for const initializer loop. X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=a7f064d5fe39ee874d9043f3bbf7427105bba51e Improve check for const initializer loop. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@169003 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 5afe163b760..21715641a42 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -2348,6 +2348,10 @@ class Const_expression : public Expression 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,23 +2614,49 @@ Const_expression::do_determine_type(const Type_context* context) } } -// 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; + 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()) { - this->report_error(_("constant refers to itself")); - this->type_ = Type::make_error_type(); + 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 @@ Find_named_object::expression(Expression** pexpr) 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;