summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/expressions.cc41
-rw-r--r--gcc/go/gofrontend/expressions.h7
-rw-r--r--gcc/go/gofrontend/parse.cc11
3 files changed, 50 insertions, 9 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 13d4c1c789a..d5e3a67625a 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -11293,7 +11293,7 @@ Field_reference_expression::do_lower(Gogo* gogo, Named_object* function,
}
Expression* e = Expression::make_composite_literal(array_type, 0, false,
- bytes, loc);
+ bytes, false, loc);
Variable* var = new Variable(array_type, e, true, false, false, loc);
@@ -13236,9 +13236,11 @@ class Composite_literal_expression : public Parser_expression
{
public:
Composite_literal_expression(Type* type, int depth, bool has_keys,
- Expression_list* vals, Location location)
+ 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)
+ type_(type), depth_(depth), vals_(vals), has_keys_(has_keys),
+ all_are_names_(all_are_names)
{ }
protected:
@@ -13256,6 +13258,7 @@ class Composite_literal_expression : public Parser_expression
(this->vals_ == NULL
? NULL
: this->vals_->copy()),
+ this->all_are_names_,
this->location());
}
@@ -13285,6 +13288,9 @@ class Composite_literal_expression : public Parser_expression
// 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_;
};
// Traversal.
@@ -13387,6 +13393,8 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
std::vector<Expression*> vals(field_count);
std::vector<int>* traverse_order = new(std::vector<int>);
Expression_list::const_iterator p = this->vals_->begin();
+ Expression* external_expr = NULL;
+ const Named_object* external_no = NULL;
while (p != this->vals_->end())
{
Expression* name_expr = *p;
@@ -13492,6 +13500,12 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
if (no != NULL)
{
+ if (no->package() != NULL && external_expr == NULL)
+ {
+ external_expr = name_expr;
+ external_no = no;
+ }
+
name = no->name();
// A predefined name won't be packed. If it starts with a
@@ -13541,6 +13555,23 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
traverse_order->push_back(index);
}
+ if (!this->all_are_names_)
+ {
+ // This is a weird case like bug462 in the testsuite.
+ if (external_expr == NULL)
+ error_at(this->location(), "unknown field in %qs literal",
+ (type->named_type() != NULL
+ ? type->named_type()->message_name().c_str()
+ : "unnamed struct"));
+ else
+ error_at(external_expr->location(), "unknown field %qs in %qs",
+ external_no->message_name().c_str(),
+ (type->named_type() != NULL
+ ? type->named_type()->message_name().c_str()
+ : "unnamed struct"));
+ return Expression::make_error(location);
+ }
+
Expression_list* list = new Expression_list;
list->reserve(field_count);
for (size_t i = 0; i < field_count; ++i)
@@ -13830,11 +13861,11 @@ Composite_literal_expression::do_dump_expression(
Expression*
Expression::make_composite_literal(Type* type, int depth, bool has_keys,
- Expression_list* vals,
+ Expression_list* vals, bool all_are_names,
Location location)
{
return new Composite_literal_expression(type, depth, has_keys, vals,
- location);
+ all_are_names, location);
}
// Return whether this expression is a composite literal.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index b4cca5453b0..bc7a25f766a 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -291,10 +291,13 @@ class Expression
make_unsafe_cast(Type*, Expression*, Location);
// Make a composite literal. The DEPTH parameter is how far down we
- // are in a list of composite literals with omitted types.
+ // are in a list of composite literals with omitted types. HAS_KEYS
+ // is true if the expression list has keys alternating with values.
+ // ALL_ARE_NAMES is true if all the keys could be struct field
+ // names.
static Expression*
make_composite_literal(Type*, int depth, bool has_keys, Expression_list*,
- Location);
+ bool all_are_names, Location);
// Make a struct composite literal.
static Expression*
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index e68f1753f87..498125bb241 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -2690,15 +2690,17 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
this->advance_token();
return Expression::make_composite_literal(type, depth, false, NULL,
- location);
+ false, location);
}
bool has_keys = false;
+ bool all_are_names = true;
Expression_list* vals = new Expression_list;
while (true)
{
Expression* val;
bool is_type_omitted = false;
+ bool is_name = false;
const Token* token = this->peek_token();
@@ -2719,6 +2721,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
val = this->id_to_expression(gogo->pack_hidden_name(identifier,
is_exported),
location);
+ is_name = true;
}
else
{
@@ -2744,6 +2747,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
{
if (has_keys)
vals->push_back(NULL);
+ is_name = false;
}
else
{
@@ -2790,6 +2794,9 @@ Parse::composite_lit(Type* type, int depth, Location location)
vals->push_back(val);
+ if (!is_name)
+ all_are_names = false;
+
if (token->is_op(OPERATOR_COMMA))
{
if (this->advance_token()->is_op(OPERATOR_RCURLY))
@@ -2830,7 +2837,7 @@ Parse::composite_lit(Type* type, int depth, Location location)
}
return Expression::make_composite_literal(type, depth, has_keys, vals,
- location);
+ all_are_names, location);
}
// FunctionLit = "func" Signature Block .