{ go_unreachable(); }
void do_dump_expression(Ast_dump_context*) const;
-
+
private:
// The type which we are representing as an expression.
Type* type_;
return false;
Expression* e = this->constant_->const_value()->expr();
-
+
this->seen_ = true;
bool r = e->numeric_constant_value(nc);
Expression*
do_copy()
{ go_unreachable(); }
-
+
void
do_dump_expression(Ast_dump_context* ast_dump_context) const
- { ast_dump_context->ostream() << "iota"; }
+ { ast_dump_context->ostream() << "iota"; }
};
// Make an iota expression. This is only called for one case: the
// know the address of this expression is being taken, we must always
// check for nil.
Unary_expression::Nil_check_classification
-Unary_expression::requires_nil_check(Gogo* gogo)
+Unary_expression::requires_nil_check(Gogo* gogo)
{
go_assert(this->op_ == OPERATOR_MULT);
go_assert(this->expr_->type()->points_to() != NULL);
{
if (this->expr_type_ != NULL)
ast_dump_context->ostream() << "(";
- ast_dump_context->dump_expression(this->expr_);
- if (this->expr_type_ != NULL)
+ ast_dump_context->dump_expression(this->expr_);
+ if (this->expr_type_ != NULL)
{
ast_dump_context->ostream() << ":";
ast_dump_context->dump_type(this->expr_type_);
ast_dump_context->ostream() << ")";
}
-
+
ast_dump_context->ostream() << "." << this->function_->name();
}
farg = farg->expr()->field_reference_expression();
}
}
-
+
if (this->is_constant())
{
Numeric_constant nc;
Call_result_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
- // FIXME: Wouldn't it be better if the call is assigned to a temporary
+ // FIXME: Wouldn't it be better if the call is assigned to a temporary
// (struct) and the fields are referenced instead.
ast_dump_context->ostream() << this->index_ << "@(";
ast_dump_context->dump_expression(this->call_);
// (expr[expr:expr:expr], expr[expr:expr] or expr[expr]) to a dump context.
void
-Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context,
- const Expression* expr,
+Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context,
+ const Expression* expr,
const Expression* start,
const Expression* end,
const Expression* cap)
// Dump ast representation for an index expression.
void
-Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
- Index_expression::dump_index_expression(ast_dump_context, this->left_,
+ Index_expression::dump_index_expression(ast_dump_context, this->left_,
this->start_, this->end_, this->cap_);
}
// Dump ast representation for an array index expression.
void
-Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
- Index_expression::dump_index_expression(ast_dump_context, this->array_,
+ Index_expression::dump_index_expression(ast_dump_context, this->array_,
this->start_, this->end_, this->cap_);
}
Bexpression* ptr = bytes->get_backend(context);
ptr = gogo->backend()->pointer_offset_expression(ptr, bstart, loc);
Btype* ubtype = Type::lookup_integer_type("uint8")->get_backend(gogo);
- Bexpression* index =
+ Bexpression* index =
gogo->backend()->indirect_expression(ubtype, ptr, true, loc);
Btype* byte_btype = bytes->type()->points_to()->get_backend(gogo);
// Dump ast representation for a map index expression
void
-Map_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+Map_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
Index_expression::dump_index_expression(ast_dump_context, this->map_,
imethod = it->find_method(name);
}
- if ((method == NULL && imethod == NULL)
+ if ((method == NULL && imethod == NULL)
|| (left_type->named_type() != NULL && left_type->points_to() != NULL))
{
if (!is_ambiguous)
++p)
results->push_back(*p);
}
-
+
Function_type* fntype = Type::make_function_type(NULL, parameters, results,
location);
if (method_type->is_varargs())
// Dump the ast for a selector expression.
void
-Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
ast_dump_context->dump_expression(this->left_);
ast_dump_context->ostream() << ".";
ast_dump_context->ostream() << this->name_;
}
-
+
// Make a selector expression.
Expression*
// Dump ast representation for an allocation expression.
void
-Allocation_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+Allocation_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
const
{
ast_dump_context->ostream() << "new(";
Type* type)
{
Location location = this->location();
+ Unordered_map(unsigned int, std::vector<Expression*>) st;
if (this->vals_ != NULL)
{
if (!this->has_keys_)
go_assert((*p)->is_error_expression());
return Expression::make_error(location);
}
+ // Check if there are duplicate constant keys.
+ if (!(*p)->is_constant())
+ continue;
+ std::string sval;
+ // Check if there are duplicate constant string keys.
+ if ((*p)->string_constant_value(&sval))
+ {
+ unsigned int h = Gogo::hash_string(sval, 0);
+ // Search the index h in the hash map.
+ Unordered_map(unsigned int, std::vector<Expression*>)::iterator mit;
+ mit = st.find(h);
+ if (mit == st.end())
+ {
+ // No duplicate since h is a new index.
+ // Create a new vector indexed by h and add it to the hash map.
+ std::vector<Expression*> l;
+ l.push_back(*p);
+ std::pair<unsigned int, std::vector<Expression*> > val(h, l);
+ st.insert(val);
+ }
+ else
+ {
+ // Do further check since index h already exists.
+ for (std::vector<Expression*>::iterator lit =
+ mit->second.begin();
+ lit != mit->second.end();
+ lit++)
+ {
+ std::string s;
+ bool ok = (*lit)->string_constant_value(&s);
+ go_assert(ok);
+ if (s == sval)
+ {
+ go_error_at((*p)->location(), ("duplicate key "
+ "in map literal"));
+ return Expression::make_error(location);
+ }
+ }
+ // Add this new string key to the vector indexed by h.
+ mit->second.push_back(*p);
+ }
+ }
}
}
ast_dump_context->ostream() << "typeinfo(";
ast_dump_context->dump_type(this->type_);
ast_dump_context->ostream() << ",";
- ast_dump_context->ostream() <<
- (this->type_info_ == TYPE_INFO_ALIGNMENT ? "alignment"
+ ast_dump_context->ostream() <<
+ (this->type_info_ == TYPE_INFO_ALIGNMENT ? "alignment"
: this->type_info_ == TYPE_INFO_FIELD_ALIGNMENT ? "field alignment"
: this->type_info_ == TYPE_INFO_SIZE ? "size"
: this->type_info_ == TYPE_INFO_BACKEND_PTRDATA ? "backend_ptrdata"
ast_dump_context->ostream() << "sliceinfo(";
this->slice_->dump_expression(ast_dump_context);
ast_dump_context->ostream() << ",";
- ast_dump_context->ostream() <<
- (this->slice_info_ == SLICE_INFO_VALUE_POINTER ? "values"
+ ast_dump_context->ostream() <<
+ (this->slice_info_ == SLICE_INFO_VALUE_POINTER ? "values"
: this->slice_info_ == SLICE_INFO_LENGTH ? "length"
: this->slice_info_ == SLICE_INFO_CAPACITY ? "capacity "
: "unknown");
void
do_dump_expression(Ast_dump_context*) const;
-
+
private:
// The type of the struct.
Struct_type* type_;
void
do_dump_expression(Ast_dump_context* ast_dump_context) const
{ ast_dump_context->ostream() << this->label_->name(); }
-
+
private:
// The label whose address we are taking.
Label* label_;
}
return ret;
-}
+}
// Check whether the constant can be expressed in a complex type.
return 0;
}
-// Return a hash code for a string, given a starting hash.
-
-unsigned int
-Type::hash_string(const std::string& s, unsigned int h)
-{
- const char* p = s.data();
- size_t len = s.length();
- for (; len > 0; --len)
- {
- h ^= *p++;
- h*= 16777619;
- }
- return h;
-}
-
// A hash table mapping unnamed types to the backend representation of
// those types.
++p)
{
hash <<= 2;
- hash = Type::hash_string(p->name(), hash);
+ hash = Gogo::hash_string(p->name(), hash);
hash += p->type()->hash_for_method(NULL, Type::COMPARE_TAGS);
}
return hash;
p != this->all_methods_->end();
++p)
{
- ret = Type::hash_string(p->name(), ret);
+ ret = Gogo::hash_string(p->name(), ret);
// We don't use the method type in the hash, to avoid
// infinite recursion if an interface method uses a type
// which is an interface which inherits from the interface
go_assert(!this->is_alias_);
const std::string& name(this->named_object()->name());
- unsigned int ret = Type::hash_string(name, 0);
+ unsigned int ret = Gogo::hash_string(name, 0);
// GOGO will be NULL here when called from Type_hash_identical.
// That is OK because that is only used for internal hash tables
{
const Package* package = this->named_object()->package();
if (package == NULL)
- ret = Type::hash_string(gogo->pkgpath(), ret);
+ ret = Gogo::hash_string(gogo->pkgpath(), ret);
else
- ret = Type::hash_string(package->pkgpath(), ret);
+ ret = Gogo::hash_string(package->pkgpath(), ret);
}
return ret;