diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 8ece73d8116..755dee5aab1 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -9e68d67d65fd72b9b4f163f2f26e15cd0d3e2cd2 +8dce33f24dd3a34e3574c1d2604428586b63c1aa 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 9037f0f2f80..09ab5bf8f7e 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -12583,69 +12583,7 @@ Map_construction_expression::do_dump_expression( ast_dump_context->ostream() << "}"; } -// A general composite literal. This is lowered to a type specific -// version. - -class Composite_literal_expression : public Parser_expression -{ - public: - Composite_literal_expression(Type* type, int depth, bool has_keys, - Expression_list* vals, bool all_are_names, - Location location) - : Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location), - type_(type), depth_(depth), vals_(vals), has_keys_(has_keys), - all_are_names_(all_are_names) - { } - - protected: - int - do_traverse(Traverse* traverse); - - Expression* - do_lower(Gogo*, Named_object*, Statement_inserter*, int); - - Expression* - do_copy() - { - return new Composite_literal_expression(this->type_, this->depth_, - this->has_keys_, - (this->vals_ == NULL - ? NULL - : this->vals_->copy()), - this->all_are_names_, - this->location()); - } - - void - do_dump_expression(Ast_dump_context*) const; - - private: - Expression* - lower_struct(Gogo*, Type*); - - Expression* - lower_array(Type*); - - Expression* - make_array(Type*, const std::vector*, Expression_list*); - - Expression* - lower_map(Gogo*, Named_object*, Statement_inserter*, Type*); - - // The type of the composite literal. - Type* type_; - // The depth within a list of composite literals within a composite - // literal, when the type is omitted. - int depth_; - // The values to put in the composite literal. - Expression_list* vals_; - // If this is true, then VALS_ is a list of pairs: a key and a - // value. In an array initializer, a missing key will be NULL. - bool has_keys_; - // If this is true, then HAS_KEYS_ is true, and every key is a - // simple identifier. - bool all_are_names_; -}; +// Class Composite_literal_expression. // Traversal. @@ -12664,12 +12602,17 @@ Composite_literal_expression::do_traverse(Traverse* traverse) // The type may not be resolvable at this point. Type* type = this->type_; - for (int depth = this->depth_; depth > 0; --depth) + for (int depth = 0; depth < this->depth_; ++depth) { if (type->array_type() != NULL) type = type->array_type()->element_type(); else if (type->map_type() != NULL) - type = type->map_type()->val_type(); + { + if (this->key_path_[depth]) + type = type->map_type()->key_type(); + else + type = type->map_type()->val_type(); + } else { // This error will be reported during lowering. @@ -12723,12 +12666,17 @@ Composite_literal_expression::do_lower(Gogo* gogo, Named_object* function, { Type* type = this->type_; - for (int depth = this->depth_; depth > 0; --depth) + for (int depth = 0; depth < this->depth_; ++depth) { if (type->array_type() != NULL) type = type->array_type()->element_type(); else if (type->map_type() != NULL) - type = type->map_type()->val_type(); + { + if (this->key_path_[depth]) + type = type->map_type()->key_type(); + else + type = type->map_type()->val_type(); + } else { if (!type->is_error()) diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 3e3950985cb..c33e63653e6 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -47,6 +47,7 @@ class Bound_method_expression; class Field_reference_expression; class Interface_field_reference_expression; class Allocation_expression; +class Composite_literal_expression; class Struct_construction_expression; class Array_construction_expression; class Fixed_array_construction_expression; @@ -691,6 +692,15 @@ class Expression allocation_expression() { return this->convert(); } + // If this is a general composite literal, return the + // Composite_literal_expression structure. Otherwise, return NULL. + Composite_literal_expression* + complit() + { + return this->convert(); + } + // If this is a struct composite literal, return the // Struct_construction_expression structure. Otherwise, return NULL. Struct_construction_expression* @@ -2890,6 +2900,87 @@ class Allocation_expression : public Expression bool allocate_on_stack_; }; +// A general composite literal. This is lowered to a type specific +// version. + +class Composite_literal_expression : public Parser_expression +{ + public: + Composite_literal_expression(Type* type, int depth, bool has_keys, + Expression_list* vals, bool all_are_names, + 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(depth)) + {} + + + // Mark the DEPTH entry of KEY_PATH as containing a key. + void + update_key_path(size_t depth) + { + go_assert(depth < this->key_path_.size()); + this->key_path_[depth] = true; + } + + protected: + int + do_traverse(Traverse* traverse); + + Expression* + do_lower(Gogo*, Named_object*, Statement_inserter*, int); + + Expression* + do_copy() + { + Composite_literal_expression *ret = + new Composite_literal_expression(this->type_, this->depth_, + this->has_keys_, + (this->vals_ == NULL + ? NULL + : this->vals_->copy()), + this->all_are_names_, + this->location()); + ret->key_path_ = this->key_path_; + return ret; + } + + void + do_dump_expression(Ast_dump_context*) const; + + private: + Expression* + lower_struct(Gogo*, Type*); + + Expression* + lower_array(Type*); + + Expression* + make_array(Type*, const std::vector*, Expression_list*); + + Expression* + lower_map(Gogo*, Named_object*, Statement_inserter*, Type*); + + // The type of the composite literal. + Type* type_; + // The depth within a list of composite literals within a composite + // literal, when the type is omitted. + int depth_; + // The values to put in the composite literal. + Expression_list* vals_; + // If this is true, then VALS_ is a list of pairs: a key and a + // value. In an array initializer, a missing key will be NULL. + bool has_keys_; + // If this is true, then HAS_KEYS_ is true, and every key is a + // simple identifier. + bool all_are_names_; + // A complement to DEPTH that indicates for each level starting from 0 to + // DEPTH-1 whether or not this composite literal is nested inside of key or + // a value. This is used to decide which type to use when given a map literal + // with omitted key types. + std::vector key_path_; +}; + // Construct a struct. class Struct_construction_expression : public Expression diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index 5c493700de6..827eb0a120a 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -2739,7 +2739,7 @@ Parse::composite_lit(Type* type, int depth, Location location) // This must be a composite literal inside another composite // literal, with the type omitted for the inner one. val = this->composite_lit(type, depth + 1, token->location()); - is_type_omitted = true; + is_type_omitted = true; } token = this->peek_token(); @@ -2751,11 +2751,14 @@ Parse::composite_lit(Type* type, int depth, Location location) } else { - if (is_type_omitted && !val->is_error_expression()) - { - error_at(this->location(), "unexpected %<:%>"); - val = Expression::make_error(this->location()); - } + if (is_type_omitted) + { + // VAL is a nested composite literal with an omitted type being + // used a key. Record this information in VAL so that the correct + // type is associated with the literal value if VAL is a + // map literal. + val->complit()->update_key_path(depth); + } this->advance_token();