compiler: let initializers hold addresses of fields
The runtime.dbgvars initializer looks like var dbgvars = []dbgVar{ {"allocfreetrace", &debug.allocfreetrace}, } Because the field address was not recognized as valid for a static initializer, the variable was initialized at runtime. Normally that would be fine, but for the runtime package it meant that dbgvars was not initialized when it was read by parsedebugvars. That meant that the GODEBUG environment variable did nothing. Fixing that revealed that the static initializer checks had to be more careful about interface types, just like the existing is_constant methods. Reviewed-on: https://go-review.googlesource.com/35891 From-SVN: r244982
This commit is contained in:
parent
42f20102ef
commit
46f7b80ec4
@ -1,4 +1,4 @@
|
||||
2c62d5223e814887801b1540162c72b90299d910
|
||||
7fa4eb4b7a32953c2e838f1b0c684a6733172b43
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -3878,35 +3878,54 @@ Unary_expression::do_is_static_initializer() const
|
||||
if (this->op_ == OPERATOR_MULT)
|
||||
return false;
|
||||
else if (this->op_ == OPERATOR_AND)
|
||||
{
|
||||
// The address of a global variable can used as a static
|
||||
// initializer.
|
||||
Var_expression* ve = this->expr_->var_expression();
|
||||
if (ve != NULL)
|
||||
{
|
||||
Named_object* no = ve->named_object();
|
||||
return no->is_variable() && no->var_value()->is_global();
|
||||
}
|
||||
|
||||
// The address of a composite literal can be used as a static
|
||||
// initializer if the composite literal is itself usable as a
|
||||
// static initializer.
|
||||
if (this->expr_->is_composite_literal()
|
||||
&& this->expr_->is_static_initializer())
|
||||
return true;
|
||||
|
||||
// The address of a string constant can be used as a static
|
||||
// initializer. This can not be written in Go itself but this
|
||||
// is used when building a type descriptor.
|
||||
if (this->expr_->string_expression() != NULL)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
return Unary_expression::base_is_static_initializer(this->expr_);
|
||||
else
|
||||
return this->expr_->is_static_initializer();
|
||||
}
|
||||
|
||||
// Return whether the address of EXPR can be used as a static
|
||||
// initializer.
|
||||
|
||||
bool
|
||||
Unary_expression::base_is_static_initializer(Expression* expr)
|
||||
{
|
||||
// The address of a field reference can be a static initializer if
|
||||
// the base can be a static initializer.
|
||||
Field_reference_expression* fre = expr->field_reference_expression();
|
||||
if (fre != NULL)
|
||||
return Unary_expression::base_is_static_initializer(fre->expr());
|
||||
|
||||
// The address of an index expression can be a static initializer if
|
||||
// the base can be a static initializer and the index is constant.
|
||||
Array_index_expression* aind = expr->array_index_expression();
|
||||
if (aind != NULL)
|
||||
return (aind->end() == NULL
|
||||
&& aind->start()->is_constant()
|
||||
&& Unary_expression::base_is_static_initializer(aind->array()));
|
||||
|
||||
// The address of a global variable can be a static initializer.
|
||||
Var_expression* ve = expr->var_expression();
|
||||
if (ve != NULL)
|
||||
{
|
||||
Named_object* no = ve->named_object();
|
||||
return no->is_variable() && no->var_value()->is_global();
|
||||
}
|
||||
|
||||
// The address of a composite literal can be used as a static
|
||||
// initializer if the composite literal is itself usable as a
|
||||
// static initializer.
|
||||
if (expr->is_composite_literal() && expr->is_static_initializer())
|
||||
return true;
|
||||
|
||||
// The address of a string constant can be used as a static
|
||||
// initializer. This can not be written in Go itself but this is
|
||||
// used when building a type descriptor.
|
||||
if (expr->string_expression() != NULL)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Apply unary opcode OP to UNC, setting NC. Return true if this
|
||||
// could be done, false if not. On overflow, issues an error and sets
|
||||
// *ISSUED_ERROR.
|
||||
@ -12460,6 +12479,17 @@ Struct_construction_expression::do_is_static_initializer() const
|
||||
if (*pv != NULL && !(*pv)->is_static_initializer())
|
||||
return false;
|
||||
}
|
||||
|
||||
const Struct_field_list* fields = this->type_->struct_type()->fields();
|
||||
for (Struct_field_list::const_iterator pf = fields->begin();
|
||||
pf != fields->end();
|
||||
++pf)
|
||||
{
|
||||
// There are no constant constructors for interfaces.
|
||||
if (pf->type()->interface_type() != NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -12550,7 +12580,7 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*,
|
||||
return this;
|
||||
|
||||
// If this is a constant struct, we don't need temporaries.
|
||||
if (this->is_constant_struct())
|
||||
if (this->is_constant_struct() || this->is_static_initializer())
|
||||
return this;
|
||||
|
||||
Location loc = this->location();
|
||||
@ -12701,6 +12731,11 @@ Array_construction_expression::do_is_static_initializer() const
|
||||
{
|
||||
if (this->vals() == NULL)
|
||||
return true;
|
||||
|
||||
// There are no constant constructors for interfaces.
|
||||
if (this->type_->array_type()->element_type()->interface_type() != NULL)
|
||||
return false;
|
||||
|
||||
for (Expression_list::const_iterator pv = this->vals()->begin();
|
||||
pv != this->vals()->end();
|
||||
++pv)
|
||||
@ -12765,7 +12800,7 @@ Array_construction_expression::do_flatten(Gogo*, Named_object*,
|
||||
return this;
|
||||
|
||||
// If this is a constant array, we don't need temporaries.
|
||||
if (this->is_constant_array())
|
||||
if (this->is_constant_array() || this->is_static_initializer())
|
||||
return this;
|
||||
|
||||
Location loc = this->location();
|
||||
|
@ -1842,6 +1842,9 @@ class Unary_expression : public Expression
|
||||
{ this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); }
|
||||
|
||||
private:
|
||||
static bool
|
||||
base_is_static_initializer(Expression*);
|
||||
|
||||
// The unary operator to apply.
|
||||
Operator op_;
|
||||
// Normally true. False if this is an address expression which does
|
||||
@ -2640,6 +2643,26 @@ class Array_index_expression : public Expression
|
||||
array() const
|
||||
{ return this->array_; }
|
||||
|
||||
// Return the index of a simple index expression, or the start index
|
||||
// of a slice expression.
|
||||
Expression*
|
||||
start()
|
||||
{ return this->start_; }
|
||||
|
||||
const Expression*
|
||||
start() const
|
||||
{ return this->start_; }
|
||||
|
||||
// Return the end index of a slice expression. This is NULL for a
|
||||
// simple index expression.
|
||||
Expression*
|
||||
end()
|
||||
{ return this->end_; }
|
||||
|
||||
const Expression*
|
||||
end() const
|
||||
{ return this->end_; }
|
||||
|
||||
protected:
|
||||
int
|
||||
do_traverse(Traverse*);
|
||||
|
Loading…
Reference in New Issue
Block a user