Commit f80d990e by Ian Lance Taylor

Don't crash on recursive consts.

From-SVN: r167899
parent a2c76d48
...@@ -2292,7 +2292,7 @@ class Const_expression : public Expression ...@@ -2292,7 +2292,7 @@ class Const_expression : public Expression
public: public:
Const_expression(Named_object* constant, source_location location) Const_expression(Named_object* constant, source_location location)
: Expression(EXPRESSION_CONST_REFERENCE, location), : Expression(EXPRESSION_CONST_REFERENCE, location),
constant_(constant), type_(NULL) constant_(constant), type_(NULL), seen_(false)
{ } { }
const std::string& const std::string&
...@@ -2350,6 +2350,9 @@ class Const_expression : public Expression ...@@ -2350,6 +2350,9 @@ class Const_expression : public Expression
// The type of this reference. This is used if the constant has an // The type of this reference. This is used if the constant has an
// abstract type. // abstract type.
Type* type_; Type* type_;
// Used to prevent infinite recursion when a constant incorrectly
// refers to itself.
mutable bool seen_;
}; };
// Lower a constant expression. This is where we convert the // Lower a constant expression. This is where we convert the
...@@ -2387,6 +2390,9 @@ bool ...@@ -2387,6 +2390,9 @@ bool
Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val, Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val,
Type** ptype) const Type** ptype) const
{ {
if (this->seen_)
return false;
Type* ctype; Type* ctype;
if (this->type_ != NULL) if (this->type_ != NULL)
ctype = this->type_; ctype = this->type_;
...@@ -2396,9 +2402,14 @@ Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val, ...@@ -2396,9 +2402,14 @@ Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val,
return false; return false;
Expression* e = this->constant_->const_value()->expr(); Expression* e = this->constant_->const_value()->expr();
this->seen_ = true;
Type* t; Type* t;
bool r = e->integer_constant_value(iota_is_constant, val, &t); bool r = e->integer_constant_value(iota_is_constant, val, &t);
this->seen_ = false;
if (r if (r
&& ctype != NULL && ctype != NULL
&& !Integer_expression::check_constant(val, ctype, this->location())) && !Integer_expression::check_constant(val, ctype, this->location()))
...@@ -2413,6 +2424,9 @@ Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val, ...@@ -2413,6 +2424,9 @@ Const_expression::do_integer_constant_value(bool iota_is_constant, mpz_t val,
bool bool
Const_expression::do_float_constant_value(mpfr_t val, Type** ptype) const Const_expression::do_float_constant_value(mpfr_t val, Type** ptype) const
{ {
if (this->seen_)
return false;
Type* ctype; Type* ctype;
if (this->type_ != NULL) if (this->type_ != NULL)
ctype = this->type_; ctype = this->type_;
...@@ -2421,9 +2435,14 @@ Const_expression::do_float_constant_value(mpfr_t val, Type** ptype) const ...@@ -2421,9 +2435,14 @@ Const_expression::do_float_constant_value(mpfr_t val, Type** ptype) const
if (ctype != NULL && ctype->float_type() == NULL) if (ctype != NULL && ctype->float_type() == NULL)
return false; return false;
this->seen_ = true;
Type* t; Type* t;
bool r = this->constant_->const_value()->expr()->float_constant_value(val, bool r = this->constant_->const_value()->expr()->float_constant_value(val,
&t); &t);
this->seen_ = false;
if (r && ctype != NULL) if (r && ctype != NULL)
{ {
if (!Float_expression::check_constant(val, ctype, this->location())) if (!Float_expression::check_constant(val, ctype, this->location()))
...@@ -2440,6 +2459,9 @@ bool ...@@ -2440,6 +2459,9 @@ bool
Const_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag, Const_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag,
Type **ptype) const Type **ptype) const
{ {
if (this->seen_)
return false;
Type* ctype; Type* ctype;
if (this->type_ != NULL) if (this->type_ != NULL)
ctype = this->type_; ctype = this->type_;
...@@ -2448,10 +2470,15 @@ Const_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag, ...@@ -2448,10 +2470,15 @@ Const_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag,
if (ctype != NULL && ctype->complex_type() == NULL) if (ctype != NULL && ctype->complex_type() == NULL)
return false; return false;
this->seen_ = true;
Type *t; Type *t;
bool r = this->constant_->const_value()->expr()->complex_constant_value(real, bool r = this->constant_->const_value()->expr()->complex_constant_value(real,
imag, imag,
&t); &t);
this->seen_ = false;
if (r && ctype != NULL) if (r && ctype != NULL)
{ {
if (!Complex_expression::check_constant(real, imag, ctype, if (!Complex_expression::check_constant(real, imag, ctype,
...@@ -2470,13 +2497,32 @@ Const_expression::do_type() ...@@ -2470,13 +2497,32 @@ Const_expression::do_type()
{ {
if (this->type_ != NULL) if (this->type_ != NULL)
return this->type_; return this->type_;
if (this->seen_)
{
this->report_error(_("constant refers to itself"));
this->type_ = Type::make_error_type();
return this->type_;
}
this->seen_ = true;
Named_constant* nc = this->constant_->const_value(); Named_constant* nc = this->constant_->const_value();
Type* ret = nc->type(); Type* ret = nc->type();
if (ret != NULL) if (ret != NULL)
return ret; {
this->seen_ = false;
return ret;
}
// During parsing, a named constant may have a NULL type, but we // During parsing, a named constant may have a NULL type, but we
// must not return a NULL type here. // must not return a NULL type here.
return nc->expr()->type(); ret = nc->expr()->type();
this->seen_ = false;
return ret;
} }
// Set the type of the const reference. // Set the type of the const reference.
......
...@@ -1472,7 +1472,8 @@ Check_types_traverse::constant(Named_object* named_object, bool) ...@@ -1472,7 +1472,8 @@ Check_types_traverse::constant(Named_object* named_object, bool)
&& !ctype->is_boolean_type() && !ctype->is_boolean_type()
&& !ctype->is_string_type()) && !ctype->is_string_type())
{ {
error_at(constant->location(), "invalid constant type"); if (!ctype->is_error_type())
error_at(constant->location(), "invalid constant type");
constant->set_error(); constant->set_error();
} }
else if (!constant->expr()->is_constant()) else if (!constant->expr()->is_constant())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment