aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-01-19 16:55:24 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-01-19 16:55:24 +0000
commit036c8f37959ccdafc6ea055ec109eb7cc3051697 (patch)
treea3d01365a21c680726d67cd1372f87eec38232d0 /gcc/go
parente3e190507a1abb4a7b1933421d669652e9179dcb (diff)
downloadgcc-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.cc54
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;