aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/expressions.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/expressions.h')
-rw-r--r--gcc/go/gofrontend/expressions.h236
1 files changed, 183 insertions, 53 deletions
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index d5df724..8763772 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -596,7 +596,8 @@ class Expression
{ return this->do_is_static_initializer(); }
// If this is not a numeric constant, return false. If it is one,
- // return true, and set VAL to hold the value.
+ // return true, and set VAL to hold the value. This method can be
+ // called before the determine_types pass.
bool
numeric_constant_value(Numeric_constant* val)
{ return this->do_numeric_constant_value(val); }
@@ -633,8 +634,7 @@ class Expression
// Return whether this expression really represents a type.
bool
- is_type_expression() const
- { return this->classification_ == EXPRESSION_TYPE; }
+ is_type_expression() const;
// If this is a const reference, return the Const_expression
// structure. Otherwise, return NULL. This is a controlled dynamic
@@ -735,6 +735,10 @@ class Expression
unary_expression()
{ return this->convert<Unary_expression, EXPRESSION_UNARY>(); }
+ const Unary_expression*
+ unary_expression() const
+ { return this->convert<const Unary_expression, EXPRESSION_UNARY>(); }
+
// If this is a binary expression, return the Binary_expression
// structure. Otherwise return NULL.
Binary_expression*
@@ -1022,10 +1026,8 @@ class Expression
void
determine_type_no_context(Gogo*);
- // Return the current type of the expression. This may be changed
- // by determine_type. This should not be called before the lowering
- // pass, unless the is_type_expression method returns true (i.e.,
- // this is an EXPRESSION_TYPE).
+ // Return the type of the expression. This should not be called
+ // before the determine_types pass.
Type*
type()
{ return this->do_type(); }
@@ -1472,17 +1474,6 @@ class Parser_expression : public Expression
virtual Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int) = 0;
- Type*
- do_type();
-
- void
- do_determine_type(Gogo*, const Type_context*)
- { go_unreachable(); }
-
- void
- do_check_types(Gogo*)
- { go_unreachable(); }
-
Bexpression*
do_get_backend(Translate_context*)
{ go_unreachable(); }
@@ -1495,7 +1486,8 @@ class Const_expression : public Expression
public:
Const_expression(Named_object* constant, Location location)
: Expression(EXPRESSION_CONST_REFERENCE, location),
- constant_(constant), type_(NULL), seen_(false)
+ constant_(constant), type_(NULL), iota_value_(0), seen_(false),
+ is_iota_(false)
{ }
Named_object*
@@ -1510,6 +1502,10 @@ class Const_expression : public Expression
void
check_for_init_loop();
+ // Set the iota value if this is a reference to iota.
+ void
+ set_iota_value(int);
+
protected:
int
do_traverse(Traverse*);
@@ -1576,9 +1572,14 @@ class Const_expression : public Expression
// The type of this reference. This is used if the constant has an
// abstract type.
Type* type_;
+ // If this const is a reference to the predeclared iota value, the
+ // value to use.
+ int iota_value_;
// Used to prevent infinite recursion when a constant incorrectly
// refers to itself.
mutable bool seen_;
+ // Whether this const is a reference to the predeclared iota value.
+ bool is_iota_;
};
// An expression which is simply a variable.
@@ -1976,8 +1977,7 @@ class Type_conversion_expression : public Expression
do_boolean_constant_value(bool*);
Type*
- do_type()
- { return this->type_; }
+ do_type();
void
do_determine_type(Gogo*, const Type_context*);
@@ -2074,7 +2074,7 @@ class Unary_expression : public Expression
Unary_expression(Operator op, Expression* expr, Location location)
: Expression(EXPRESSION_UNARY, location),
op_(op), escapes_(true), create_temp_(false), is_gc_root_(false),
- is_slice_init_(false), expr_(expr),
+ is_slice_init_(false), expr_(expr), type_(NULL),
issue_nil_check_(NIL_CHECK_DEFAULT)
{ }
@@ -2131,7 +2131,7 @@ class Unary_expression : public Expression
// could be done, false if not. On overflow, issues an error and
// sets *ISSUED_ERROR.
static bool
- eval_constant(Operator op, const Numeric_constant* unc,
+ eval_constant(Type*, Operator op, const Numeric_constant* unc,
Location, Numeric_constant* nc, bool *issued_error);
static Expression*
@@ -2246,6 +2246,8 @@ class Unary_expression : public Expression
bool is_slice_init_;
// The operand.
Expression* expr_;
+ // The type of the expression. Not used for AND and MULT.
+ Type* type_;
// Whether or not to issue a nil check for this expression if its address
// is being taken.
Nil_check_classification issue_nil_check_;
@@ -2372,15 +2374,15 @@ class Binary_expression : public Expression
static bool
eval_integer(Operator op, const Numeric_constant*, const Numeric_constant*,
- Location, Numeric_constant*);
+ Location, Numeric_constant*, bool* issued_error);
static bool
eval_float(Operator op, const Numeric_constant*, const Numeric_constant*,
- Location, Numeric_constant*);
+ Location, Numeric_constant*, bool* issued_error);
static bool
eval_complex(Operator op, const Numeric_constant*, const Numeric_constant*,
- Location, Numeric_constant*);
+ Location, Numeric_constant*, bool* issued_error);
static bool
compare_integer(const Numeric_constant*, const Numeric_constant*, int*);
@@ -2412,7 +2414,7 @@ class Binary_expression : public Expression
Expression* left_;
// The right hand side operand.
Expression* right_;
- // The type of a comparison operation.
+ // The type of the expression.
Type* type_;
};
@@ -2493,8 +2495,8 @@ class Call_expression : public Expression
Call_expression(Expression* fn, Expression_list* args, bool is_varargs,
Location location)
: Expression(EXPRESSION_CALL, location),
- fn_(fn), args_(args), type_(NULL), call_(NULL), call_temp_(NULL)
- , expected_result_count_(0), is_varargs_(is_varargs),
+ fn_(fn), args_(args), type_(NULL), lowered_(NULL), call_(NULL),
+ call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs),
varargs_are_lowered_(false), types_are_determined_(false),
is_deferred_(false), is_concurrent_(false), is_equal_function_(false),
issued_error_(false), is_multi_value_arg_(false), is_flattened_(false)
@@ -2530,7 +2532,8 @@ class Call_expression : public Expression
// Set the number of results expected from this call. This is used
// when the call appears in a context that expects multiple results,
- // such as a, b = f().
+ // such as a, b = f(). This must be called before the
+ // determine_types pass.
void
set_expected_result_count(size_t);
@@ -2616,6 +2619,10 @@ class Call_expression : public Expression
inline const Builtin_call_expression*
builtin_call_expression() const;
+ // Lower to a Builtin_call_expression if appropriate.
+ Expression*
+ lower_builtin(Gogo*);
+
protected:
int
do_traverse(Traverse*);
@@ -2627,12 +2634,20 @@ class Call_expression : public Expression
do_flatten(Gogo*, Named_object*, Statement_inserter*);
bool
- do_discarding_value()
- { return true; }
+ do_discarding_value();
virtual Type*
do_type();
+ virtual bool
+ do_is_constant() const;
+
+ bool
+ do_is_untyped(Type**) const;
+
+ bool
+ do_numeric_constant_value(Numeric_constant*);
+
virtual void
do_determine_type(Gogo*, const Type_context*);
@@ -2665,17 +2680,26 @@ class Call_expression : public Expression
set_args(Expression_list* args)
{ this->args_ = args; }
- // Let a builtin expression lower varargs.
- void
- lower_varargs(Gogo*, Named_object* function, Statement_inserter* inserter,
- Type* varargs_type, size_t param_count,
- Slice_storage_escape_disp escape_disp);
-
// Let a builtin expression check whether types have been
// determined.
bool
determining_types();
+ // Let a builtin expression retrieve the expected type.
+ Type*
+ type()
+ { return this->type_; }
+
+ // Let a builtin expression set the expected type.
+ void
+ set_type(Type* type)
+ { this->type_ = type; }
+
+ // Let a builtin expression simply f(g()) where g returns multiple
+ // results.
+ void
+ simplify_multiple_results(Gogo*);
+
void
export_arguments(Export_function_body*) const;
@@ -2687,7 +2711,10 @@ class Call_expression : public Expression
private:
bool
- check_argument_type(int, const Type*, const Type*, Location, bool);
+ rewrite_varargs();
+
+ bool
+ check_argument_type(int, const Type*, const Type*, Location);
Expression*
intrinsify(Gogo*, Statement_inserter*);
@@ -2706,6 +2733,8 @@ class Call_expression : public Expression
Expression_list* args_;
// The type of the expression, to avoid recomputing it.
Type* type_;
+ // If not NULL, this is a lowered version of this Call_expression.
+ Expression* lowered_;
// The backend expression for the call, used for a call which returns a tuple.
Bexpression* call_;
// A temporary variable to store this call if the function returns a tuple.
@@ -3087,7 +3116,8 @@ class Unknown_expression : public Parser_expression
public:
Unknown_expression(Named_object* named_object, Location location)
: Parser_expression(EXPRESSION_UNKNOWN_REFERENCE, location),
- named_object_(named_object), no_error_message_(false)
+ named_object_(named_object), lowered_(NULL), iota_value_(0),
+ no_error_message_(false), is_iota_(false)
{ }
// The associated named object.
@@ -3106,7 +3136,38 @@ class Unknown_expression : public Parser_expression
set_no_error_message()
{ this->no_error_message_ = true; }
+ // Set the iota value if this is a reference to iota.
+ void
+ set_iota_value(int);
+
protected:
+ int
+ do_traverse(Traverse*);
+
+ Type*
+ do_type();
+
+ void
+ do_determine_type(Gogo*, const Type_context*);
+
+ bool
+ do_is_constant() const;
+
+ bool
+ do_is_untyped(Type**) const;
+
+ virtual bool
+ do_numeric_constant_value(Numeric_constant*);
+
+ virtual bool
+ do_string_constant_value(std::string*);
+
+ virtual bool
+ do_boolean_constant_value(bool*);
+
+ bool
+ do_is_addressable() const;
+
Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
@@ -3120,9 +3181,15 @@ class Unknown_expression : public Parser_expression
private:
// The unknown name.
Named_object* named_object_;
+ // The fully resolved expression.
+ Expression* lowered_;
+ // The iota value if this turns out to be a reference to iota.
+ int iota_value_;
// True if we should not give errors if this is undefined. This is
// used if there was a parse failure.
bool no_error_message_;
+ // True if this could be a reference to iota.
+ bool is_iota_;
};
// An index expression. This is lowered to an array index, a string
@@ -3134,9 +3201,15 @@ class Index_expression : public Parser_expression
Index_expression(Expression* left, Expression* start, Expression* end,
Expression* cap, Location location)
: Parser_expression(EXPRESSION_INDEX, location),
- left_(left), start_(start), end_(end), cap_(cap)
+ left_(left), start_(start), end_(end), cap_(cap),
+ needs_nil_check_(false)
{ }
+ // Return the expression being indexed.
+ Expression*
+ left() const
+ { return this->left_; }
+
// Dump an index expression, i.e. an expression of the form
// expr[expr], expr[expr:expr], or expr[expr:expr:expr] to a dump context.
static void
@@ -3144,24 +3217,44 @@ class Index_expression : public Parser_expression
const Expression* start, const Expression* end,
const Expression* cap);
+ // Report whether EXPR is a map index expression.
+ static bool
+ is_map_index(Expression* expr);
+
protected:
int
do_traverse(Traverse*);
+ Type*
+ do_type();
+
+ void
+ do_determine_type(Gogo*, const Type_context*);
+
+ void
+ do_check_types(Gogo*);
+
+ bool
+ do_is_addressable() const;
+
Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
Expression*
do_copy()
{
- return new Index_expression(this->left_->copy(), this->start_->copy(),
- (this->end_ == NULL
- ? NULL
- : this->end_->copy()),
- (this->cap_ == NULL
- ? NULL
- : this->cap_->copy()),
- this->location());
+ Index_expression* ret =
+ new Index_expression(this->left_->copy(), this->start_->copy(),
+ (this->end_ == NULL
+ ? NULL
+ : this->end_->copy()),
+ (this->cap_ == NULL
+ ? NULL
+ : this->cap_->copy()),
+ this->location());
+ if (this->needs_nil_check_)
+ ret->needs_nil_check_ = true;
+ return ret;
}
// This shouldn't be called--we don't know yet.
@@ -3173,8 +3266,8 @@ class Index_expression : public Parser_expression
do_dump_expression(Ast_dump_context*) const;
void
- do_issue_nil_check()
- { this->left_->issue_nil_check(); }
+ do_issue_nil_check();
+
private:
// The expression being indexed.
Expression* left_;
@@ -3187,6 +3280,9 @@ class Index_expression : public Parser_expression
// default capacity, non-NULL for indices and slices that specify the
// capacity.
Expression* cap_;
+ // True if this needs a nil check. This changes how we handle
+ // dereferencing a pointer to an array.
+ bool needs_nil_check_;
};
// An array index. This is used for both indexing and slicing.
@@ -3234,6 +3330,11 @@ class Array_index_expression : public Expression
set_needs_bounds_check(bool b)
{ this->needs_bounds_check_ = b; }
+ // Check indexes.
+ static bool
+ check_indexes(Expression* array, Expression* start, Expression* len,
+ Expression* cap, Location);
+
protected:
int
do_traverse(Traverse*);
@@ -3339,6 +3440,11 @@ class String_index_expression : public Expression
end() const
{ return this->end_; }
+ // Check indexes.
+ static bool
+ check_indexes(Expression* string, Expression* start, Expression* len,
+ Location);
+
protected:
int
do_traverse(Traverse*);
@@ -3832,7 +3938,8 @@ class Composite_literal_expression : public Parser_expression
Location location)
: Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location),
type_(type), depth_(depth), vals_(vals), has_keys_(has_keys),
- all_are_names_(all_are_names), key_path_(std::vector<bool>(depth))
+ all_are_names_(all_are_names), key_path_(std::vector<bool>(depth)),
+ traverse_order_(NULL)
{}
@@ -3848,6 +3955,15 @@ class Composite_literal_expression : public Parser_expression
int
do_traverse(Traverse* traverse);
+ Type*
+ do_type();
+
+ void
+ do_determine_type(Gogo*, const Type_context*);
+
+ void
+ do_check_types(Gogo*);
+
Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
@@ -3858,8 +3974,14 @@ class Composite_literal_expression : public Parser_expression
do_dump_expression(Ast_dump_context*) const;
private:
+ bool
+ resolve_struct_keys(Gogo*, Type* type);
+
+ void
+ resolve_array_length(Type*);
+
Expression*
- lower_struct(Gogo*, Type*);
+ lower_struct(Type*);
Expression*
lower_array(Type*);
@@ -3888,6 +4010,10 @@ class Composite_literal_expression : public Parser_expression
// a value. This is used to decide which type to use when given a map literal
// with omitted key types.
std::vector<bool> key_path_;
+ // If not NULL, the order in which to traverse vals_ for a struct
+ // composite literal. This is used so that we implement the order
+ // of evaluation rules correctly.
+ std::vector<unsigned long>* traverse_order_;
};
// Helper/mixin class for struct and array construction expressions;
@@ -3948,6 +4074,10 @@ class Struct_construction_expression : public Expression,
bool
is_constant_struct() const;
+ // Check types of a struct composite literal.
+ static bool
+ check_value_types(Gogo*, Type*, Expression_list*, Location);
+
protected:
int
do_traverse(Traverse* traverse);