ac50e9b72bf9bb6d5b28096bb164fb050db6e290 diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 0f961157dfd..d4095637cea 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -081ec9824a74ec9d82628d8d2f6b9a7a4c35a529 +1c0a7c9338801d15afba7e39109554ed3406654e The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 273831fabf3..5bea6238def 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -201,6 +201,19 @@ Expression::report_error(const char* msg) this->set_is_error(); } +// A convenience function for handling a type in do_is_untyped. If +// TYPE is not abstract, return false. Otherwise set *PTYPE to TYPE +// and return true. + +bool +Expression::is_untyped_type(Type* type, Type** ptype) +{ + if (!type->is_abstract()) + return false; + *ptype = type; + return true; +} + // Set types of variables and constants. This is implemented by the // child class. @@ -826,6 +839,10 @@ class Error_expression : public Expression do_is_constant() const { return true; } + bool + do_is_untyped(Type**) const + { return false; } + bool do_numeric_constant_value(Numeric_constant* nc) const { @@ -1965,6 +1982,9 @@ class Boolean_expression : public Expression do_is_constant() const { return true; } + bool + do_is_untyped(Type**) const; + bool do_is_zero_value() const { return this->val_ == false; } @@ -2023,6 +2043,15 @@ Boolean_expression::do_traverse(Traverse* traverse) return TRAVERSE_CONTINUE; } +bool +Boolean_expression::do_is_untyped(Type** ptype) const +{ + if (this->type_ != NULL) + return Expression::is_untyped_type(this->type_, ptype); + *ptype = Type::make_boolean_type(); + return true; +} + // Get the type. Type* @@ -2096,6 +2125,15 @@ String_expression::do_traverse(Traverse* traverse) return TRAVERSE_CONTINUE; } +bool +String_expression::do_is_untyped(Type** ptype) const +{ + if (this->type_ != NULL) + return Expression::is_untyped_type(this->type_, ptype); + *ptype = Type::make_string_type(); + return true; +} + // Get the type. Type* @@ -2485,6 +2523,9 @@ class Integer_expression : public Expression do_is_constant() const { return true; } + bool + do_is_untyped(Type**) const; + bool do_is_zero_value() const { return mpz_sgn(this->val_) == 0; } @@ -2568,6 +2609,18 @@ Integer_expression::do_numeric_constant_value(Numeric_constant* nc) const return true; } +bool +Integer_expression::do_is_untyped(Type** ptype) const +{ + if (this->type_ != NULL) + return Expression::is_untyped_type(this->type_, ptype); + if (this->is_character_constant_) + *ptype = Type::make_abstract_character_type(); + else + *ptype = Type::make_abstract_integer_type(); + return true; +} + // Return the current type. If we haven't set the type yet, we return // an abstract integer type. @@ -2913,6 +2966,9 @@ class Float_expression : public Expression do_is_constant() const { return true; } + bool + do_is_untyped(Type**) const; + bool do_is_zero_value() const { @@ -2979,6 +3035,15 @@ Float_expression::do_traverse(Traverse* traverse) return TRAVERSE_CONTINUE; } +bool +Float_expression::do_is_untyped(Type** ptype) const +{ + if (this->type_ != NULL) + return Expression::is_untyped_type(this->type_, ptype); + *ptype = Type::make_abstract_float_type(); + return true; +} + // Return the current type. If we haven't set the type yet, we return // an abstract float type. @@ -3135,6 +3200,9 @@ class Complex_expression : public Expression do_is_constant() const { return true; } + bool + do_is_untyped(Type**) const; + bool do_is_zero_value() const { @@ -3205,6 +3273,15 @@ Complex_expression::do_traverse(Traverse* traverse) return TRAVERSE_CONTINUE; } +bool +Complex_expression::do_is_untyped(Type** ptype) const +{ + if (this->type_ != NULL) + return Expression::is_untyped_type(this->type_, ptype); + *ptype = Type::make_abstract_complex_type(); + return true; +} + // Return the current type. If we haven't set the type yet, we return // an abstract complex type. @@ -3458,6 +3535,21 @@ Const_expression::do_boolean_constant_value(bool* val) const return ok; } +// Whether this is untyped. + +bool +Const_expression::do_is_untyped(Type** ptype) const +{ + if (this->type_ != NULL) + return Expression::is_untyped_type(this->type_, ptype); + + Named_constant* nc = this->constant_->const_value(); + if (nc->type() != NULL) + return Expression::is_untyped_type(nc->type(), ptype); + + return nc->expr()->is_untyped(ptype); +} + // Return the type of the const reference. Type* @@ -3707,6 +3799,13 @@ class Nil_expression : public Expression do_is_constant() const { return true; } + bool + do_untyped_type(Type** ptype) const + { + *ptype = Type::make_nil_type(); + return true; + } + bool do_is_zero_value() const { return true; } @@ -4774,6 +4873,14 @@ Unary_expression::do_is_constant() const return this->expr_->is_constant(); } +bool +Unary_expression::do_is_untyped(Type** ptype) const +{ + if (this->op_ == OPERATOR_MULT || this->op_ == OPERATOR_AND) + return false; + return this->expr_->is_untyped(ptype); +} + // Return whether a unary expression can be used as a constant // initializer. @@ -5523,6 +5630,81 @@ Binary_expression::do_traverse(Traverse* traverse) return Expression::traverse(&this->right_, traverse); } +// Return whether a binary expression is untyped. + +bool +Binary_expression::do_is_untyped(Type** ptype) const +{ + if (this->type_ != NULL) + return Expression::is_untyped_type(this->type_, ptype); + + switch (this->op_) + { + case OPERATOR_EQEQ: + case OPERATOR_NOTEQ: + case OPERATOR_LT: + case OPERATOR_LE: + case OPERATOR_GT: + case OPERATOR_GE: + // Comparisons are untyped by default. + *ptype = Type::make_boolean_type(); + return true; + + case OPERATOR_LSHIFT: + case OPERATOR_RSHIFT: + // A shift operation is untyped if the left hand expression is + // untyped. The right hand expression is irrelevant. + return this->left_->is_untyped(ptype); + + default: + break; + } + + Type* tleft; + Type* tright; + if (!this->left_->is_untyped(&tleft) + || !this->right_->is_untyped(&tright)) + return false; + + // If both sides are numeric, pick a type based on the kind. + enum kind { INT, RUNE, FLOAT, COMPLEX }; + enum kind kleft, kright; + + if (tleft->integer_type() != NULL) + kleft = tleft->integer_type()->is_rune() ? RUNE : INT; + else if (tleft->float_type() != NULL) + kleft = FLOAT; + else if (tleft->complex_type() != NULL) + kleft = COMPLEX; + else + { + // Not numeric. If the types are different, we will report an + // error later. + *ptype = tleft; + return true; + } + + if (tright->integer_type() != NULL) + kright = tright->integer_type()->is_rune() ? RUNE : INT; + else if (tright->float_type() != NULL) + kright = FLOAT; + else if (tright->complex_type() != NULL) + kright = COMPLEX; + else + { + // Types are different. We will report an error later. + *ptype = tleft; + return true; + } + + if (kleft > kright) + *ptype = tleft; + else + *ptype = tright; + + return true; +} + // Return whether this expression may be used as a static initializer. bool @@ -7645,6 +7827,21 @@ String_concat_expression::do_is_constant() const return true; } +bool +String_concat_expression::do_is_untyped(Type** ptype) const +{ + for (Expression_list::iterator pe = this->exprs_->begin(); + pe != this->exprs_->end(); + ++pe) + { + if (!(*pe)->is_untyped(ptype)) + return false; + } + + *ptype = Type::make_string_type(); + return true; +} + bool String_concat_expression::do_is_zero_value() const { @@ -9671,6 +9868,47 @@ Builtin_call_expression::do_is_constant() const return false; } +// Return whether a builtin call is untyped. Most builtin functions +// have a known type, but complex, real, and imag can be untyped. + +bool +Builtin_call_expression::do_is_untyped(Type** ptype) const +{ + if (this->is_error_expression()) + return false; + + switch (this->code_) + { + default: + return false; + + case BUILTIN_COMPLEX: + { + const Expression_list* args = this->args(); + if (args == NULL || args->size() != 2) + return false; + Type* dummy; + if (!args->front()->is_untyped(&dummy) + || !args->back()->is_untyped(&dummy)) + return false; + *ptype = Type::make_abstract_complex_type(); + return true; + } + + case BUILTIN_REAL: + case BUILTIN_IMAG: + { + Expression* arg = this->one_arg(); + if (arg == NULL) + return false; + if (!arg->is_untyped(ptype)) + return false; + *ptype = Type::make_abstract_float_type(); + return true; + } + } +} + // Return a numeric constant if possible. bool diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 2abc9cb8425..49140d100a4 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -566,6 +566,15 @@ class Expression is_constant() const { return this->do_is_constant(); } + // Return whether this expression is untyped. This isn't quite the + // same as is_constant with an abstract type, as 1<do_is_untyped(ptype); } + // Return whether this is the zero value of its type. bool is_zero_value() const @@ -1169,6 +1178,11 @@ class Expression do_is_constant() const { return false; } + // Return whether this expression is untyped. + virtual bool + do_is_untyped(Type**) const + { return false; } + // Return whether this is the zero value of its type. virtual bool do_is_zero_value() const @@ -1274,6 +1288,12 @@ class Expression void report_error(const char*); + // A convenience function for handling a type in do_is_untyped. If + // TYPE is not abstract, return false. Otherwise set *PTYPE to TYPE + // and return true. + static bool + is_untyped_type(Type* type, Type** ptype); + // Write a name to export data. static void export_name(Export_function_body* efb, const Named_object*); @@ -1501,6 +1521,9 @@ class Const_expression : public Expression do_is_constant() const { return true; } + bool + do_is_untyped(Type**) const; + bool do_is_zero_value() const; @@ -1830,6 +1853,9 @@ class String_expression : public Expression do_is_constant() const { return true; } + bool + do_is_untyped(Type**) const; + bool do_is_zero_value() const { return this->val_ == ""; } @@ -2136,6 +2162,9 @@ class Unary_expression : public Expression bool do_is_constant() const; + bool + do_is_untyped(Type**) const; + bool do_is_static_initializer() const; @@ -2293,6 +2322,9 @@ class Binary_expression : public Expression do_is_constant() const { return this->left_->is_constant() && this->right_->is_constant(); } + bool + do_is_untyped(Type**) const; + bool do_is_static_initializer() const; @@ -2415,6 +2447,9 @@ class String_concat_expression : public Expression bool do_is_constant() const; + bool + do_is_untyped(Type**) const; + bool do_is_zero_value() const; @@ -2767,6 +2802,9 @@ class Builtin_call_expression : public Call_expression bool do_is_constant() const; + bool + do_is_untyped(Type**) const; + bool do_numeric_constant_value(Numeric_constant*) const;