// 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),
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.
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.
}
}
+ 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;
}
{
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.
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;
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())
{
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 "
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;