diff options
Diffstat (limited to 'gcc/go/gofrontend/expressions.h')
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 236 |
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); |