compiler: Error for qualified ID as field name in struct literal.

From-SVN: r203292
This commit is contained in:
Ian Lance Taylor 2013-10-08 23:54:15 +00:00
parent a81169d8fa
commit 8ae4c35c1e
3 changed files with 50 additions and 9 deletions

View File

@ -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.

View File

@ -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*

View File

@ -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 .