-e0790a756e9ba77e2d3d6ef5d0abbb11dd71211b
+8ad32fb3e1e8b19ac125d03db24a73a800abdfa6
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
real = no->unknown_value()->real_named_object();
if (real == NULL)
{
- if (this->is_composite_literal_key_)
- return this;
if (!this->no_error_message_)
go_error_at(location, "reference to undefined name %qs",
this->named_object_->message_name().c_str());
case Named_object::NAMED_OBJECT_TYPE:
return Expression::make_type(real->type_value(), location);
case Named_object::NAMED_OBJECT_TYPE_DECLARATION:
- if (this->is_composite_literal_key_)
- return this;
if (!this->no_error_message_)
go_error_at(location, "reference to undefined type %qs",
real->message_name().c_str());
case Named_object::NAMED_OBJECT_FUNC_DECLARATION:
return Expression::make_func_reference(real, NULL, location);
case Named_object::NAMED_OBJECT_PACKAGE:
- if (this->is_composite_literal_key_)
- return this;
if (!this->no_error_message_)
go_error_at(location, "unexpected reference to package");
return Expression::make_error(location);
ast_dump_context->ostream() << "}";
}
+// A composite literal key. This is seen during parsing, but is not
+// resolved to a named_object in case this is a composite literal of
+// struct type.
+
+class Composite_literal_key_expression : public Parser_expression
+{
+ public:
+ Composite_literal_key_expression(const std::string& name, Location location)
+ : Parser_expression(EXPRESSION_COMPOSITE_LITERAL_KEY, location),
+ name_(name)
+ { }
+
+ const std::string&
+ name() const
+ { return this->name_; }
+
+ protected:
+ Expression*
+ do_lower(Gogo*, Named_object*, Statement_inserter*, int);
+
+ Expression*
+ do_copy()
+ {
+ return new Composite_literal_key_expression(this->name_, this->location());
+ }
+
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
+ private:
+ // The name.
+ std::string name_;
+};
+
+// Lower a composite literal key. We will never get here for keys in
+// composite literals of struct types, because that is prevented by
+// Composite_literal_expression::do_traverse. So if we do get here,
+// this must be a regular name reference after all.
+
+Expression*
+Composite_literal_key_expression::do_lower(Gogo* gogo, Named_object*,
+ Statement_inserter*, int)
+{
+ Named_object* no = gogo->lookup(this->name_, NULL);
+ if (no == NULL)
+ {
+ go_error_at(this->location(), "reference to undefined name %qs",
+ Gogo::message_name(this->name_).c_str());
+ return Expression::make_error(this->location());
+ }
+ return Expression::make_unknown_reference(no, this->location());
+}
+
+// Dump a composite literal key.
+
+void
+Composite_literal_key_expression::do_dump_expression(
+ Ast_dump_context* ast_dump_context) const
+{
+ ast_dump_context->ostream() << "_UnknownName_(" << this->name_ << ")";
+}
+
+// Make a composite literal key.
+
+Expression*
+Expression::make_composite_literal_key(const std::string& name,
+ Location location)
+{
+ return new Composite_literal_key_expression(name, location);
+}
+
// Class Composite_literal_expression.
// Traversal.
for (int depth = 0; depth < this->depth_; ++depth)
{
+ type = type->deref();
if (type->array_type() != NULL)
type = type->array_type()->element_type();
else if (type->map_type() != NULL)
return TRAVERSE_CONTINUE;
}
}
+ type = type->deref();
while (true)
{
const Named_object* no = NULL;
switch (name_expr->classification())
{
+ case EXPRESSION_COMPOSITE_LITERAL_KEY:
+ name =
+ static_cast<Composite_literal_key_expression*>(name_expr)->name();
+ break;
+
case EXPRESSION_UNKNOWN_REFERENCE:
name = name_expr->unknown_expression()->name();
if (type->named_type() != NULL)
// literals. Lower it now to get the right error message.
if ((*p)->unknown_expression() != NULL)
{
- (*p)->unknown_expression()->clear_is_composite_literal_key();
gogo->lower_expression(function, inserter, &*p);
go_assert((*p)->is_error_expression());
return Expression::make_error(location);
EXPRESSION_SLICE_CONSTRUCTION,
EXPRESSION_MAP_CONSTRUCTION,
EXPRESSION_COMPOSITE_LITERAL,
+ EXPRESSION_COMPOSITE_LITERAL_KEY,
EXPRESSION_HEAP,
EXPRESSION_RECEIVE,
EXPRESSION_TYPE_DESCRIPTOR,
make_composite_literal(Type*, int depth, bool has_keys, Expression_list*,
bool all_are_names, Location);
+ // Make a composite literal key.
+ static Expression*
+ make_composite_literal_key(const std::string& name, Location);
+
// Make a struct composite literal.
static Expression*
make_struct_composite_literal(Type*, Expression_list*, Location);
public:
Unknown_expression(Named_object* named_object, Location location)
: Parser_expression(EXPRESSION_UNKNOWN_REFERENCE, location),
- named_object_(named_object), no_error_message_(false),
- is_composite_literal_key_(false)
+ named_object_(named_object), no_error_message_(false)
{ }
// The associated named object.
set_no_error_message()
{ this->no_error_message_ = true; }
- // Note that this expression is being used as the key in a composite
- // literal, so it may be OK if it is not resolved.
- void
- set_is_composite_literal_key()
- { this->is_composite_literal_key_ = true; }
-
- // Note that this expression should no longer be treated as a
- // composite literal key.
- void
- clear_is_composite_literal_key()
- { this->is_composite_literal_key_ = false; }
-
protected:
Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
// True if we should not give errors if this is undefined. This is
// used if there was a parse failure.
bool no_error_message_;
- // True if this is the key in a composite literal.
- bool is_composite_literal_key_;
};
// An index expression. This is lowered to an array index, a string
p != til.end();
++p)
exprs->push_back(this->id_to_expression(p->name(), p->location(),
- true));
+ true, false));
Expression_list* more_exprs =
this->expression_list(NULL, true, may_be_composite_lit);
Gogo* gogo = this->gogo_;
val = this->id_to_expression(gogo->pack_hidden_name(identifier,
is_exported),
- id_location, false);
+ id_location, false, true);
is_name = true;
}
else
}
has_keys = true;
- if (val->unknown_expression() != NULL)
- val->unknown_expression()->set_is_composite_literal_key();
-
vals->push_back(val);
if (!token->is_op(OPERATOR_LCURLY))
Expression*
Parse::id_to_expression(const std::string& name, Location location,
- bool is_lhs)
+ bool is_lhs, bool is_composite_literal_key)
{
Named_object* in_function;
Named_object* named_object = this->gogo_->lookup(name, &in_function);
if (named_object == NULL)
- named_object = this->gogo_->add_unknown_name(name, location);
+ {
+ if (is_composite_literal_key)
+ {
+ // This is a composite literal key, which means that it
+ // could just be a struct field name, so avoid confusiong by
+ // not adding it to the bindings. We'll look up the name
+ // later during the lowering phase if necessary.
+ return Expression::make_composite_literal_key(name, location);
+ }
+ named_object = this->gogo_->add_unknown_name(name, location);
+ }
if (in_function != NULL
&& in_function != this->gogo_->current_function()
*val = this->id_to_expression(gogo->pack_hidden_name(recv_var,
is_rv_exported),
- recv_var_loc, true);
+ recv_var_loc, true, false);
saw_comma = true;
}
else
bool* is_type_switch, bool* is_parenthesized);
Type* reassociate_chan_direction(Channel_type*, Location);
Expression* qualified_expr(Expression*, Location);
- Expression* id_to_expression(const std::string&, Location, bool);
+ Expression* id_to_expression(const std::string&, Location, bool, bool);
void statement(Label*);
bool statement_may_start_here();
void labeled_stmt(const std::string&, Location);