aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2014-12-01 01:29:45 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-12-01 01:29:45 +0000
commit975fbd84776bc813d2c6cc020682b1e692400d38 (patch)
tree85d3bba7ae43598fe57d332fbb7e5e0a3f012a12 /gcc
parent4368bc458974b45ad284780fef222242046ad9f9 (diff)
downloadgcc-975fbd84776bc813d2c6cc020682b1e692400d38.zip
gcc-975fbd84776bc813d2c6cc020682b1e692400d38.tar.gz
gcc-975fbd84776bc813d2c6cc020682b1e692400d38.tar.bz2
compiler: Don't crash with self-referential types.
Fixes issue 6637. From-SVN: r218199
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/expressions.cc11
-rw-r--r--gcc/go/gofrontend/expressions.h2
-rw-r--r--gcc/go/gofrontend/types.cc30
-rw-r--r--gcc/go/gofrontend/types.h11
4 files changed, 44 insertions, 10 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index dba5ea0..024b2c4 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -8735,7 +8735,11 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
// Add temporary variables for all arguments that require type
// conversion.
Function_type* fntype = this->get_function_type();
- go_assert(fntype != NULL);
+ if (fntype == NULL)
+ {
+ go_assert(saw_errors());
+ return this;
+ }
if (this->args_ != NULL && !this->args_->empty()
&& fntype->parameters() != NULL && !fntype->parameters()->empty())
{
@@ -10901,9 +10905,8 @@ Interface_field_reference_expression::do_traverse(Traverse* traverse)
// interface. So introduce a temporary variable if necessary.
Expression*
-Interface_field_reference_expression::do_lower(Gogo*, Named_object*,
- Statement_inserter* inserter,
- int)
+Interface_field_reference_expression::do_flatten(Gogo*, Named_object*,
+ Statement_inserter* inserter)
{
if (!this->expr_->is_variable())
{
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index b7e1806..d96df28 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -2397,7 +2397,7 @@ class Interface_field_reference_expression : public Expression
do_traverse(Traverse* traverse);
Expression*
- do_lower(Gogo*, Named_object*, Statement_inserter*, int);
+ do_flatten(Gogo*, Named_object*, Statement_inserter*);
Type*
do_type();
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index c85c72c..7035524 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -6361,7 +6361,13 @@ Array_type::do_reflection(Gogo* gogo, std::string* ret) const
unsigned long val;
if (!this->length_->numeric_constant_value(&nc)
|| nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
- error_at(this->length_->location(), "invalid array length");
+ {
+ if (!this->issued_length_error_)
+ {
+ error_at(this->length_->location(), "invalid array length");
+ this->issued_length_error_ = true;
+ }
+ }
else
{
char buf[50];
@@ -6488,7 +6494,13 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
unsigned long val;
if (!this->length_->numeric_constant_value(&nc)
|| nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
- error_at(this->length_->location(), "invalid array length");
+ {
+ if (!this->issued_length_error_)
+ {
+ error_at(this->length_->location(), "invalid array length");
+ this->issued_length_error_ = true;
+ }
+ }
else
{
char buf[50];
@@ -10221,7 +10233,12 @@ Type*
Forward_declaration_type::real_type()
{
if (this->is_defined())
- return this->named_object()->type_value();
+ {
+ Named_type* nt = this->named_object()->type_value();
+ if (!nt->is_valid())
+ return Type::make_error_type();
+ return this->named_object()->type_value();
+ }
else
{
this->warn();
@@ -10233,7 +10250,12 @@ const Type*
Forward_declaration_type::real_type() const
{
if (this->is_defined())
- return this->named_object()->type_value();
+ {
+ const Named_type* nt = this->named_object()->type_value();
+ if (!nt->is_valid())
+ return Type::make_error_type();
+ return this->named_object()->type_value();
+ }
else
{
this->warn();
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 60de22e..4f000b1 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -2360,7 +2360,8 @@ class Array_type : public Type
public:
Array_type(Type* element_type, Expression* length)
: Type(TYPE_ARRAY),
- element_type_(element_type), length_(length), blength_(NULL)
+ element_type_(element_type), length_(length), blength_(NULL),
+ issued_length_error_(false)
{ }
// Return the element type.
@@ -2479,6 +2480,9 @@ class Array_type : public Type
// The backend representation of the length.
// We only want to compute this once.
Bexpression* blength_;
+ // Whether or not an invalid length error has been issued for this type,
+ // to avoid knock-on errors.
+ mutable bool issued_length_error_;
};
// The type of a map.
@@ -2926,6 +2930,11 @@ class Named_type : public Type
bool
is_alias() const;
+ // Whether this named type is valid. A recursive named type is invalid.
+ bool
+ is_valid() const
+ { return !this->is_error_; }
+
// Whether this is a circular type: a pointer or function type that
// refers to itself, which is not possible in C.
bool