@@ -2937,8 +2937,8 @@
}
}
- return Expression::make_composite_literal(type, false, vals,
- location);
+ return Expression::make_slice_composite_literal(type, vals,
+ location);
}
}
}
@@ -7823,14 +7823,19 @@
vals->push_back(*pa);
}
- Type* ctype;
+ Expression* val;
if (element_type == NULL)
- ctype = Type::make_struct_type(fields, loc);
+ {
+ Type* ctype = Type::make_struct_type(fields, loc);
+ val = Expression::make_struct_composite_literal(ctype, vals, loc);
+ }
else
- ctype = Type::make_array_type(element_type, NULL);
-
- new_args->push_back(Expression::make_composite_literal(ctype, false,
- vals, loc));
+ {
+ Type* ctype = Type::make_array_type(element_type, NULL);
+ val = Expression::make_slice_composite_literal(ctype, vals, loc);
+ }
+
+ new_args->push_back(val);
}
}
@@ -7842,9 +7847,9 @@
{
Struct_field_list* fields = new Struct_field_list();
Type* param_type = Type::make_struct_type(fields, loc);
- new_args->push_back(Expression::make_composite_literal(param_type,
- false, NULL,
- loc));
+ Expression* v = Expression::make_struct_composite_literal(param_type,
+ NULL, loc);
+ new_args->push_back(v);
}
}
@@ -10962,10 +10967,10 @@
class Composite_literal_expression : public Parser_expression
{
public:
- Composite_literal_expression(Type* type, bool has_keys,
+ Composite_literal_expression(Type* type, int depth, bool has_keys,
Expression_list* vals, source_location location)
: Parser_expression(EXPRESSION_COMPOSITE_LITERAL, location),
- type_(type), vals_(vals), has_keys_(has_keys)
+ type_(type), depth_(depth), vals_(vals), has_keys_(has_keys)
{ }
protected:
@@ -10978,7 +10983,8 @@
Expression*
do_copy()
{
- return new Composite_literal_expression(this->type_, this->has_keys_,
+ return new Composite_literal_expression(this->type_, this->depth_,
+ this->has_keys_,
(this->vals_ == NULL
? NULL
: this->vals_->copy()),
@@ -10987,19 +10993,22 @@
private:
Expression*
- lower_struct();
+ lower_struct(Type*);
Expression*
- lower_array();
+ lower_array(Type*);
Expression*
- make_array(Expression_list*);
+ make_array(Type*, Expression_list*);
Expression*
- lower_map();
+ lower_map(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
@@ -11025,18 +11034,36 @@
Composite_literal_expression::do_lower(Gogo*, Named_object*, int)
{
Type* type = this->type_;
+
+ for (int depth = this->depth_; depth > 0; --depth)
+ {
+ if (type->array_type() != NULL)
+ type = type->array_type()->element_type();
+ else if (type->map_type() != NULL)
+ type = type->map_type()->val_type();
+ else
+ {
+ if (!type->is_error_type())
+ error_at(this->location(),
+ ("may only omit types within composite literals "
+ "of slice, array, or map type"));
+ return Expression::make_error(this->location());
+ }
+ }
+
if (type->is_error_type())
return Expression::make_error(this->location());
else if (type->struct_type() != NULL)
- return this->lower_struct();
+ return this->lower_struct(type);
else if (type->array_type() != NULL)
- return this->lower_array();
+ return this->lower_array(type);
else if (type->map_type() != NULL)
- return this->lower_map();
+ return this->lower_map(type);
else
{
error_at(this->location(),
- "expected struct, array, or map type for composite literal");
+ ("expected struct, slice, array, or map type "
+ "for composite literal"));
return Expression::make_error(this->location());
}
}
@@ -11044,13 +11071,12 @@
// Lower a struct composite literal.
Expression*
-Composite_literal_expression::lower_struct()
+Composite_literal_expression::lower_struct(Type* type)
{
source_location location = this->location();
- Struct_type* st = this->type_->struct_type();
+ Struct_type* st = type->struct_type();
if (this->vals_ == NULL || !this->has_keys_)
- return new Struct_construction_expression(this->type_, this->vals_,
- location);
+ return new Struct_construction_expression(type, this->vals_, location);
size_t field_count = st->field_count();
std::vector<Expression*> vals(field_count);
@@ -11153,8 +11179,8 @@
{
error_at(name_expr->location(), "unknown field %qs in %qs",
Gogo::unpack_hidden_name(name).c_str(),
- (this->type_->named_type() != NULL
- ? this->type_->named_type()->message_name().c_str()
+ (type->named_type() != NULL
+ ? type->named_type()->message_name().c_str()
: "unnamed struct"));
return Expression::make_error(location);
}
@@ -11163,8 +11189,8 @@
error_at(name_expr->location(),
"duplicate value for field %qs in %qs",
Gogo::unpack_hidden_name(name).c_str(),
- (this->type_->named_type() != NULL
- ? this->type_->named_type()->message_name().c_str()
+ (type->named_type() != NULL
+ ? type->named_type()->message_name().c_str()
: "unnamed struct"));
return Expression::make_error(location);
}
@@ -11177,17 +11203,17 @@
for (size_t i = 0; i < field_count; ++i)
list->push_back(vals[i]);
- return new Struct_construction_expression(this->type_, list, location);
+ return new Struct_construction_expression(type, list, location);
}
// Lower an array composite literal.
Expression*
-Composite_literal_expression::lower_array()
+Composite_literal_expression::lower_array(Type* type)
{
source_location location = this->location();
if (this->vals_ == NULL || !this->has_keys_)
- return this->make_array(this->vals_);
+ return this->make_array(type, this->vals_);
std::vector<Expression*> vals;
vals.reserve(this->vals_->size());
@@ -11261,17 +11287,17 @@
for (size_t i = 0; i < size; ++i)
list->push_back(vals[i]);
- return this->make_array(list);
+ return this->make_array(type, list);
}
// Actually build the array composite literal. This handles
// [...]{...}.
Expression*
-Composite_literal_expression::make_array(Expression_list* vals)
+Composite_literal_expression::make_array(Type* type, Expression_list* vals)
{
source_location location = this->location();
- Array_type* at = this->type_->array_type();
+ Array_type* at = type->array_type();
if (at->length() != NULL && at->length()->is_nil_expression())
{
size_t size = vals == NULL ? 0 : vals->size();
@@ -11280,18 +11306,18 @@
Expression* elen = Expression::make_integer(&vlen, NULL, location);
mpz_clear(vlen);
at = Type::make_array_type(at->element_type(), elen);
- this->type_ = at;
+ type = at;
}
if (at->length() != NULL)
- return new Fixed_array_construction_expression(this->type_, vals, location);
+ return new Fixed_array_construction_expression(type, vals, location);
else
- return new Open_array_construction_expression(this->type_, vals, location);
+ return new Open_array_construction_expression(type, vals, location);
}
// Lower a map composite literal.
Expression*
-Composite_literal_expression::lower_map()
+Composite_literal_expression::lower_map(Type* type)
{
source_location location = this->location();
if (this->vals_ != NULL)
@@ -11316,17 +11342,18 @@
}
}
- return new Map_construction_expression(this->type_, this->vals_, location);
+ return new Map_construction_expression(type, this->vals_, location);
}
// Make a composite literal expression.
Expression*
-Expression::make_composite_literal(Type* type, bool has_keys,
+Expression::make_composite_literal(Type* type, int depth, bool has_keys,
Expression_list* vals,
source_location location)
{
- return new Composite_literal_expression(type, has_keys, vals, location);
+ return new Composite_literal_expression(type, depth, has_keys, vals,
+ location);
}
// Return whether this expression is a composite literal.
@@ -248,9 +248,10 @@
static Expression*
make_cast(Type*, Expression*, source_location);
- // Make a composite literal.
+ // Make a composite literal. The DEPTH parameter is how far down we
+ // are in a list of composite literals with omitted types.
static Expression*
- make_composite_literal(Type*, bool has_keys, Expression_list*,
+ make_composite_literal(Type*, int depth, bool has_keys, Expression_list*,
source_location);
// Make a struct composite literal.
@@ -2314,19 +2314,25 @@
return e;
}
-// CompositeLit = LiteralType "{" [ ElementList ] "}" .
+// CompositeLit = LiteralType LiteralValue .
// LiteralType = StructType | ArrayType | "[" "..." "]" ElementType |
// SliceType | MapType | TypeName .
-// ElementList = Element { "," Element } [ "," ] .
+// LiteralValue = "{" [ ElementList [ "," ] ] "}" .
+// ElementList = Element { "," Element } .
// Element = [ Key ":" ] Value .
// Key = Expression .
-// Value = Expression .
-
-// We have already seen the type. The case "[" "..." "]" ElementType
-// will be seen here as an array type whose length is "nil".
+// Value = Expression | LiteralValue .
+
+// We have already seen the type if there is one, and we are now
+// looking at the LiteralValue. The case "[" "..." "]" ElementType
+// will be seen here as an array type whose length is "nil". The
+// DEPTH parameter is non-zero if this is an embedded composite
+// literal and the type was omitted. It gives the number of steps up
+// to the type which was provided. E.g., in [][]int{{1}} it will be
+// 1. In [][][]int{{{1}}} it will be 2.
Expression*
-Parse::composite_lit(Type* type, source_location location)
+Parse::composite_lit(Type* type, int depth, source_location location)
{
gcc_assert(this->peek_token()->is_op(OPERATOR_LCURLY));
this->advance_token();
@@ -2334,16 +2340,30 @@
if (this->peek_token()->is_op(OPERATOR_RCURLY))
{
this->advance_token();
- return Expression::make_composite_literal(type, false, NULL, location);
+ return Expression::make_composite_literal(type, depth, false, NULL,
+ location);
}
bool has_keys = false;
Expression_list* vals = new Expression_list;
while (true)
{
- Expression* val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ Expression* val;
+ bool is_type_omitted = false;
const Token* token = this->peek_token();
+
+ if (!token->is_op(OPERATOR_LCURLY))
+ val = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ else
+ {
+ // 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;
+ }
+
+ token = this->peek_token();
if (!token->is_op(OPERATOR_COLON))
{
if (has_keys)
@@ -2351,6 +2371,12 @@
}
else
{
+ if (is_type_omitted && !val->is_error_expression())
+ {
+ this->error("unexpected %<:%>");
+ val = Expression::make_error(this->location());
+ }
+
this->advance_token();
if (!has_keys && !vals->empty())
@@ -2414,7 +2440,8 @@
}
}
- return Expression::make_composite_literal(type, has_keys, vals, location);
+ return Expression::make_composite_literal(type, depth, has_keys, vals,
+ location);
}
// FunctionLit = "func" Signature Block .
@@ -2540,7 +2567,7 @@
if (is_parenthesized)
error_at(start_loc,
"cannot parenthesize type in composite literal");
- ret = this->composite_lit(ret->type(), ret->location());
+ ret = this->composite_lit(ret->type(), 0, ret->location());
}
else if (this->peek_token()->is_op(OPERATOR_LPAREN))
{
@@ -206,7 +206,7 @@
Expression* operand(bool may_be_sink);
Expression* enclosing_var_reference(Named_object*, Named_object*,
source_location);
- Expression* composite_lit(Type*, source_location);
+ Expression* composite_lit(Type*, int depth, source_location);
Expression* function_lit();
Expression* create_closure(Named_object* function, Enclosing_vars*,
source_location);