aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2013-01-29 00:28:09 +0000
committerIan Lance Taylor <iant@google.com>2013-01-29 00:28:09 +0000
commit0b5392b5baedcb99550376537cb6da054be03cde (patch)
tree3116a655f079f6c96c8bc21c712270ddc3f3cf5c /gcc/go
parent8215c4927ac640edc3564d7d86ac5eb8e4672e18 (diff)
compiler: Correct initialization order determination.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@195526 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/expressions.h5
-rw-r--r--gcc/go/gofrontend/gogo-tree.cc73
-rw-r--r--gcc/go/gofrontend/statements.h5
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()