diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-01-29 00:28:09 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-01-29 00:28:09 +0000 |
commit | 12ab9655524cede6f3c27ce1aa737b406f54917c (patch) | |
tree | 3116a655f079f6c96c8bc21c712270ddc3f3cf5c /gcc/go | |
parent | 670c28f56201211c011c7bd7e633db4d2eb4bce1 (diff) | |
download | gcc-12ab9655524cede6f3c27ce1aa737b406f54917c.tar.gz |
compiler: Correct initialization order determination.
From-SVN: r195526
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 5 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo-tree.cc | 73 | ||||
-rw-r--r-- | gcc/go/gofrontend/statements.h | 5 |
3 files changed, 53 insertions, 30 deletions
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 152c2232454..af178de5c4e 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -983,6 +983,11 @@ class Temporary_reference_expression : public Expression 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 // assignment statement. void diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc index e6eb37e0bbd..b9840451955 100644 --- a/gcc/go/gofrontend/gogo-tree.cc +++ b/gcc/go/gofrontend/gogo-tree.cc @@ -499,7 +499,7 @@ class Find_var : public Traverse // 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 // package. - typedef Unordered_set(std::string) Seen_objects; + typedef Unordered_set(const void*) Seen_objects; Find_var(Named_object* var, Seen_objects* seen_objects) : Traverse(traverse_expressions), @@ -547,7 +547,7 @@ Find_var::expression(Expression** pexpr) if (init != NULL) { std::pair<Seen_objects::iterator, bool> ins = - this->seen_objects_->insert(v->name()); + this->seen_objects_->insert(v); if (ins.second) { // This is the first time we have seen this name. @@ -568,7 +568,7 @@ Find_var::expression(Expression** pexpr) if (f->is_function() && f->package() == NULL) { std::pair<Seen_objects::iterator, bool> ins = - this->seen_objects_->insert(f->name()); + this->seen_objects_->insert(f); if (ins.second) { // This is the first time we have seen this name. @@ -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; } @@ -613,11 +632,11 @@ class Var_init { public: Var_init() - : var_(NULL), init_(NULL_TREE), waiting_(0) + : var_(NULL), init_(NULL_TREE) { } Var_init(Named_object* var, tree init) - : var_(var), init_(init), waiting_(0) + : var_(var), init_(init) { } // Return the variable. @@ -630,24 +649,11 @@ class Var_init init() const { 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: // The variable being initialized. Named_object* var_; // The initialization expression to run. tree init_; - // The number of variables which are waiting for this one. - size_t waiting_; }; typedef std::list<Var_init> Var_inits; @@ -660,6 +666,10 @@ typedef std::list<Var_init> Var_inits; static void 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; while (!var_inits->empty()) { @@ -670,23 +680,30 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits) Named_object* dep = gogo->var_depends_on(var->var_value()); // Start walking through the list to see which variables VAR - // needs to wait for. We can skip P1->WAITING variables--that - // is the number we've already checked. + // needs to wait for. Var_inits::iterator p2 = p1; ++p2; - for (size_t i = p1->waiting(); i > 0; --i) - ++p2; for (; p2 != var_inits->end(); ++p2) { 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. - 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(), gogo->var_depends_on(p2var->var_value()), - var)) + var); + if (ins.first->second) { error_at(var->location(), ("initialization expressions for %qs and " @@ -700,12 +717,8 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits) else { // 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; - for (size_t i = p2->waiting(); i > 0; --i) - ++p3; + ++p3; var_inits->splice(p3, *var_inits, p1); } break; diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index 5bbfd373669..c5995710792 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -490,6 +490,11 @@ class Temporary_statement : public Statement Type* 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. void set_hidden_fields_are_ok() |