diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-01-19 16:55:24 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-01-19 16:55:24 +0000 |
commit | 036c8f37959ccdafc6ea055ec109eb7cc3051697 (patch) | |
tree | a3d01365a21c680726d67cd1372f87eec38232d0 /gcc/go | |
parent | e3e190507a1abb4a7b1933421d669652e9179dcb (diff) | |
download | gcc-036c8f37959ccdafc6ea055ec109eb7cc3051697.zip gcc-036c8f37959ccdafc6ea055ec109eb7cc3051697.tar.gz gcc-036c8f37959ccdafc6ea055ec109eb7cc3051697.tar.bz2 |
Improve check for const initializer loop.
From-SVN: r169003
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 5afe163..2171564 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<Const_expression*>(*pexpr)->named_object() == this->no_) - break; - return TRAVERSE_CONTINUE; + { + Const_expression* ce = static_cast<Const_expression*>(*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; |