aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2016-01-27 18:51:58 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-01-27 18:51:58 +0000
commitb45285fc2ee430b675f57e8c92310aaf77ba031e (patch)
tree668ea53d0e4fe91b41cc2d1c49cd4d7983cee20b /gcc/go
parent8f91e6e0eff1494cfefb2129876847aab5748538 (diff)
downloadgcc-b45285fc2ee430b675f57e8c92310aaf77ba031e.zip
gcc-b45285fc2ee430b675f57e8c92310aaf77ba031e.tar.gz
gcc-b45285fc2ee430b675f57e8c92310aaf77ba031e.tar.bz2
compiler: Accept map composite literals with omitted key types.
compiler: Copy key_path_ when copying a Composite_literal_expression. Fixes golang/go#10263. Reviewed-on: https://go-review.googlesource.com/14299 Reviewed-on: https://go-review.googlesource.com/18988 From-SVN: r232892
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc82
-rw-r--r--gcc/go/gofrontend/expressions.h91
-rw-r--r--gcc/go/gofrontend/parse.cc15
4 files changed, 116 insertions, 74 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 8ece73d..755dee5 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 9037f0f..09ab5bf 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<unsigned long>*, 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 3e39509..c33e636 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<Allocation_expression, EXPRESSION_ALLOCATION>(); }
+ // If this is a general composite literal, return the
+ // Composite_literal_expression structure. Otherwise, return NULL.
+ Composite_literal_expression*
+ complit()
+ {
+ return this->convert<Composite_literal_expression,
+ EXPRESSION_COMPOSITE_LITERAL>();
+ }
+
// 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<bool>(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<unsigned long>*, 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<bool> 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 5c49370..827eb0a 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();