@@ -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.
@@ -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
@@ -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<<val is untyped
+ // even if val is a variable. If this returns true, it sets *PTYPE
+ // to an abstract type, which is the type the expression will have
+ // if there is no context.
+ bool
+ is_untyped(Type** ptype) const
+ { return this->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;