Commit 12ab9655 by Ian Lance Taylor

compiler: Correct initialization order determination.

From-SVN: r195526
parent 670c28f5
...@@ -983,6 +983,11 @@ class Temporary_reference_expression : public Expression ...@@ -983,6 +983,11 @@ class Temporary_reference_expression : public Expression
statement_(statement), is_lvalue_(false) statement_(statement), is_lvalue_(false)
{ } { }
// The temporary that this expression refers to.
Temporary_statement*
statement() const
{ return this->statement_; }
// Indicate that this reference appears on the left hand side of an // Indicate that this reference appears on the left hand side of an
// assignment statement. // assignment statement.
void void
......
...@@ -499,7 +499,7 @@ class Find_var : public Traverse ...@@ -499,7 +499,7 @@ class Find_var : public Traverse
// A hash table we use to avoid looping. The index is the name of a // A hash table we use to avoid looping. The index is the name of a
// named object. We only look through objects defined in this // named object. We only look through objects defined in this
// package. // package.
typedef Unordered_set(std::string) Seen_objects; typedef Unordered_set(const void*) Seen_objects;
Find_var(Named_object* var, Seen_objects* seen_objects) Find_var(Named_object* var, Seen_objects* seen_objects)
: Traverse(traverse_expressions), : Traverse(traverse_expressions),
...@@ -547,7 +547,7 @@ Find_var::expression(Expression** pexpr) ...@@ -547,7 +547,7 @@ Find_var::expression(Expression** pexpr)
if (init != NULL) if (init != NULL)
{ {
std::pair<Seen_objects::iterator, bool> ins = std::pair<Seen_objects::iterator, bool> ins =
this->seen_objects_->insert(v->name()); this->seen_objects_->insert(v);
if (ins.second) if (ins.second)
{ {
// This is the first time we have seen this name. // This is the first time we have seen this name.
...@@ -568,7 +568,7 @@ Find_var::expression(Expression** pexpr) ...@@ -568,7 +568,7 @@ Find_var::expression(Expression** pexpr)
if (f->is_function() && f->package() == NULL) if (f->is_function() && f->package() == NULL)
{ {
std::pair<Seen_objects::iterator, bool> ins = std::pair<Seen_objects::iterator, bool> ins =
this->seen_objects_->insert(f->name()); this->seen_objects_->insert(f);
if (ins.second) if (ins.second)
{ {
// This is the first time we have seen this name. // This is the first time we have seen this name.
...@@ -578,6 +578,25 @@ Find_var::expression(Expression** pexpr) ...@@ -578,6 +578,25 @@ Find_var::expression(Expression** pexpr)
} }
} }
Temporary_reference_expression* tre = e->temporary_reference_expression();
if (tre != NULL)
{
Temporary_statement* ts = tre->statement();
Expression* init = ts->init();
if (init != NULL)
{
std::pair<Seen_objects::iterator, bool> ins =
this->seen_objects_->insert(ts);
if (ins.second)
{
// This is the first time we have seen this temporary
// statement.
if (Expression::traverse(&init, this) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
}
}
return TRAVERSE_CONTINUE; return TRAVERSE_CONTINUE;
} }
...@@ -613,11 +632,11 @@ class Var_init ...@@ -613,11 +632,11 @@ class Var_init
{ {
public: public:
Var_init() Var_init()
: var_(NULL), init_(NULL_TREE), waiting_(0) : var_(NULL), init_(NULL_TREE)
{ } { }
Var_init(Named_object* var, tree init) Var_init(Named_object* var, tree init)
: var_(var), init_(init), waiting_(0) : var_(var), init_(init)
{ } { }
// Return the variable. // Return the variable.
...@@ -630,24 +649,11 @@ class Var_init ...@@ -630,24 +649,11 @@ class Var_init
init() const init() const
{ return this->init_; } { return this->init_; }
// Return the number of variables waiting for this one to be
// initialized.
size_t
waiting() const
{ return this->waiting_; }
// Increment the number waiting.
void
increment_waiting()
{ ++this->waiting_; }
private: private:
// The variable being initialized. // The variable being initialized.
Named_object* var_; Named_object* var_;
// The initialization expression to run. // The initialization expression to run.
tree init_; tree init_;
// The number of variables which are waiting for this one.
size_t waiting_;
}; };
typedef std::list<Var_init> Var_inits; typedef std::list<Var_init> Var_inits;
...@@ -660,6 +666,10 @@ typedef std::list<Var_init> Var_inits; ...@@ -660,6 +666,10 @@ typedef std::list<Var_init> Var_inits;
static void static void
sort_var_inits(Gogo* gogo, Var_inits* var_inits) sort_var_inits(Gogo* gogo, Var_inits* var_inits)
{ {
typedef std::pair<Named_object*, Named_object*> No_no;
typedef std::map<No_no, bool> Cache;
Cache cache;
Var_inits ready; Var_inits ready;
while (!var_inits->empty()) while (!var_inits->empty())
{ {
...@@ -670,23 +680,30 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits) ...@@ -670,23 +680,30 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits)
Named_object* dep = gogo->var_depends_on(var->var_value()); Named_object* dep = gogo->var_depends_on(var->var_value());
// Start walking through the list to see which variables VAR // Start walking through the list to see which variables VAR
// needs to wait for. We can skip P1->WAITING variables--that // needs to wait for.
// is the number we've already checked.
Var_inits::iterator p2 = p1; Var_inits::iterator p2 = p1;
++p2; ++p2;
for (size_t i = p1->waiting(); i > 0; --i)
++p2;
for (; p2 != var_inits->end(); ++p2) for (; p2 != var_inits->end(); ++p2)
{ {
Named_object* p2var = p2->var(); Named_object* p2var = p2->var();
if (expression_requires(init, preinit, dep, p2var)) No_no key(var, p2var);
std::pair<Cache::iterator, bool> ins =
cache.insert(std::make_pair(key, false));
if (ins.second)
ins.first->second = expression_requires(init, preinit, dep, p2var);
if (ins.first->second)
{ {
// Check for cycles. // Check for cycles.
if (expression_requires(p2var->var_value()->init(), key = std::make_pair(p2var, var);
ins = cache.insert(std::make_pair(key, false));
if (ins.second)
ins.first->second =
expression_requires(p2var->var_value()->init(),
p2var->var_value()->preinit(), p2var->var_value()->preinit(),
gogo->var_depends_on(p2var->var_value()), gogo->var_depends_on(p2var->var_value()),
var)) var);
if (ins.first->second)
{ {
error_at(var->location(), error_at(var->location(),
("initialization expressions for %qs and " ("initialization expressions for %qs and "
...@@ -700,11 +717,7 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits) ...@@ -700,11 +717,7 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits)
else else
{ {
// We can't emit P1 until P2 is emitted. Move P1. // We can't emit P1 until P2 is emitted. Move P1.
// Note that the WAITING loop always executes at
// least once, which is what we want.
p2->increment_waiting();
Var_inits::iterator p3 = p2; Var_inits::iterator p3 = p2;
for (size_t i = p2->waiting(); i > 0; --i)
++p3; ++p3;
var_inits->splice(p3, *var_inits, p1); var_inits->splice(p3, *var_inits, p1);
} }
......
...@@ -490,6 +490,11 @@ class Temporary_statement : public Statement ...@@ -490,6 +490,11 @@ class Temporary_statement : public Statement
Type* Type*
type() const; type() const;
// Return the initializer if there is one.
Expression*
init() const
{ return this->init_; }
// Note that it is OK for this statement to set hidden fields. // Note that it is OK for this statement to set hidden fields.
void void
set_hidden_fields_are_ok() set_hidden_fields_are_ok()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment