Skip to content
Snippets Groups Projects
VisitTable.cpp 64.32 KiB
/**************************************************************************/
/*                                                                        */
/*  This file is part of Frama-Clang                                      */
/*                                                                        */
/*  Copyright (C) 2012-2022                                               */
/*    CEA (Commissariat à l'énergie atomique et aux énergies              */
/*         alternatives)                                                  */
/*                                                                        */
/*  you can redistribute it and/or modify it under the terms of the GNU   */
/*  Lesser General Public License as published by the Free Software       */
/*  Foundation, version 2.1.                                              */
/*                                                                        */
/*  It is distributed in the hope that it will be useful,                 */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
/*  GNU Lesser General Public License for more details.                   */
/*                                                                        */
/*  See the GNU Lesser General Public License version 2.1                 */
/*  for more details (enclosed in the file LICENSE).                      */
/*                                                                        */
/**************************************************************************/

//
// Description:
//   Implementation of VisitTable
//

#include "VisitTable.h"

void
VisitTable::MissingSubClassGeneration::print(std::ostream& out, bool ident)
      const {
  out << std::endl;
  for (int i = 0; i < ident; ++i)
    out << "  ";
  const clang::NamedDecl* decl = llvm::dyn_cast<clang::NamedDecl>
      (_key);
  if (decl)
    out << decl->getNameAsString() << ": ";
  else
    out << "clang_unnamed: ";
  if (_waitingSubClassDecl) {
    assert(_waitingSubClassDecl->tag_class_decl == CCOMPOUND);
    out << "non-generated subclass " << _waitingSubClassDecl
      ->cons_class_decl.CCompound.name << ": ";
  };
  if (!_additionalWaitDeclarations.empty()) {
    out << "waiting for ";
    std::vector<const clang::Decl*>::const_iterator
      iterEnd = _additionalWaitDeclarations.end(),
      iter = _additionalWaitDeclarations.begin();
    while (iter != iterEnd) {
      const clang::NamedDecl* decl = llvm::dyn_cast<clang::NamedDecl>
          (*iter);
      if (decl)
        out << decl->getNameAsString();
      else
        out << "clang_unnamed";
      ++iter;
      if (iter != iterEnd)
        out << ", ";
    };
  };
  if (!_subGenerations.empty()) {
    std::vector<MissingSubClassGeneration>::const_iterator
      iterEnd = _subGenerations.end(), iter = _subGenerations.begin();
    for (; iter != iterEnd; ++iter) {
      out << '\n';
      iter->print(out, ident+1);
    };
  };
}

bool
VisitTable::MissingSubClassGeneration::removeWait(const clang::Decl* decl) {
  std::vector<const clang::Decl*>::iterator
      iterEnd = _additionalWaitDeclarations.end();
  class_decl* parentDecl = &_waitingSubClassDecl;
  /* class_decl */ list* parentDeclList = NULL;
  int parentDeclPosition = 0;
  for (std::vector<const clang::Decl*>::iterator iter
      = _additionalWaitDeclarations.begin(); iter != iterEnd; ++iter) {
    if (*iter == decl) {
      _additionalWaitDeclarations.erase(iter);
      if (_additionalWaitDeclarations.empty()) {
        _waitingSubClassDecl = NULL;
        return _subGenerations.empty();
      };
      return false;
    };
  };
  std::set<const clang::Decl*>::iterator found
      = _subWaitDeclarations.find(decl);
  if (found != _subWaitDeclarations.end()) {
    std::vector<MissingSubClassGeneration>::iterator subIterEnd
        = _subGenerations.end();
    int subIndex = 0;
    for (std::vector<MissingSubClassGeneration>::iterator subIter
        = _subGenerations.begin(); subIter != subIterEnd; ) {
      if (subIter->removeWaitWithinClass(decl, parentDeclList,
          (/* class_decl */ list*)
            &(*parentDecl)->cons_class_decl.CCompound.body->content.container,
          parentDeclPosition, subIter->_parentPosition - subIndex)) {
        _subGenerations.erase(subIter);
        if (_subGenerations.empty()) {
          assert(_subWaitDeclarations.size() == 1);
          _subWaitDeclarations.clear();
          return _additionalWaitDeclarations.empty();
        };
        subIterEnd = _subGenerations.end();
      }
      else
        ++subIter;
      ++subIndex;
    }
    _subWaitDeclarations.erase(found);
  };
  return false;
}

bool
VisitTable::MissingSubClassGeneration::replaceWaitingBy(
    const clang::Decl* oldDecl, const std::vector<const clang::Decl*>& newDecls)
{ bool hasFoundInMain = false;
  { std::vector<const clang::Decl*>::iterator iterEnd
      = _additionalWaitDeclarations.end();
    std::vector<const clang::Decl*>::iterator
      iter = _additionalWaitDeclarations.begin();
    for (; !hasFoundInMain && iter != iterEnd; ++iter)
      hasFoundInMain = (*iter) == oldDecl;
    if (hasFoundInMain)
      _additionalWaitDeclarations.erase(iter);
  };
  if (hasFoundInMain) {
    int targetSize = _additionalWaitDeclarations.size();
    std::vector<const clang::Decl*>::const_iterator sourceIterEnd
        = newDecls.end();
    for (std::vector<const clang::Decl*>::const_iterator sourceIter
        = newDecls.begin(); sourceIter != sourceIterEnd; ++sourceIter) {
      bool hasFound = false;
      for (int targetIndex = 0; !hasFound && targetIndex < targetSize; 
          ++targetIndex)
        hasFound = *sourceIter
            == _additionalWaitDeclarations[targetIndex];
      if (!hasFound)
        _additionalWaitDeclarations.push_back(*sourceIter);
    };
  }
  else {
    std::set<const clang::Decl*>::iterator found = _subWaitDeclarations
      .find(oldDecl);
    if (found != _subWaitDeclarations.end()) {
      _subWaitDeclarations.erase(found);
      std::vector<const clang::Decl*>::const_iterator sourceIterEnd
        = newDecls.end();
      for (std::vector<const clang::Decl*>::const_iterator sourceIter
          = newDecls.begin(); sourceIter != sourceIterEnd; ++sourceIter)
        _subWaitDeclarations.insert(*sourceIter);
      std::vector<MissingSubClassGeneration>::iterator
          subIterEnd = _subGenerations.end();
      for (std::vector<MissingSubClassGeneration>::iterator subIter
          = _subGenerations.begin(); subIter != subIterEnd; ++subIter)
        subIter->replaceWaitingBy(oldDecl, newDecls);
    };
  }
  return true;
}

#if 0

bool
VisitTable::MissingSubClassGeneration::solve(const clang::Decl* decl,
    MissingClassGeneration& parentDecl, ForwardReferenceList& globals,
    VisitTable& table) {
  assert(_waitingSubClassDecl);
  bool result = _additionalWaitDeclarations.size() == 1;
  if (result) {
    if (*_additionalWaitDeclarations.begin() == decl) {
      std::vector<MissingSubClassGeneration>::iterator subIterEnd
          = _subGenerations.end();
      std::vector<MissingSubClassGeneration>::iterator subIter
          = _subGenerations.begin();
      /* class_decl */ list* parentDeclList = NULL;
      int parentDeclPosition = 0;
      int subIndex = 0;
      while (subIter != subIterEnd && (!subIter->_waitingSubClassDecl
          || subIter->removeWaitWithinClass(decl, parentDeclList,
               (/* class_decl */ list*) &_waitingSubClassDecl->cons_class_decl
                 .CCompound.body->content.container,
               parentDeclPosition, subIter->_parentPosition - subIndex))) {
        table.solve(*subIter, parentDecl, globals);
        ++subIter; ++subIndex;
      };
      if (subIter != subIterEnd) {
        assert(_waitingSubClassDecl->tag_class_decl == CCOMPOUND
            && _waitingSubClassDecl->cons_class_decl.CCompound.body->is_some);
        /* class_decl */ list subList = _waitingSubClassDecl->cons_class_decl
            .CCompound.body->content.container;
        assert(subList);
        while (subList) {
          class_decl classElement = (class_decl) subList->element.container;
          bool isEqual = classElement == subIter->_waitingSubClassDecl;
          if (!isEqual)
            isEqual = classElement->tag_class_decl == CCOMPOUND
              && subIter->_waitingSubClassDecl->tag_class_decl == CCOMPOUND
              && !strcmp(classElement->cons_class_decl.CCompound.name,
                  subIter->_waitingSubClassDecl->cons_class_decl.CCompound.name)
              && tkind_equal(
                  classElement->cons_class_decl.CCompound.template_kind,
                  subIter->_waitingSubClassDecl->cons_class_decl
                    .CCompound.template_kind);
          if (isEqual) {
            table.addWaitFor(*subIter, subIter->_waitingSubClassDecl,
              &parentDecl, globals,
              classElement!=subIter->_waitingSubClassDecl /* shouldBeSubkey */);
            ++subIter; ++subIndex;
            while (subIter != subIterEnd && (!subIter->_waitingSubClassDecl
                || subIter->removeWaitWithinClass(decl, parentDeclList,
                     (/* class_decl */ list*) &_waitingSubClassDecl
                       ->cons_class_decl.CCompound.body->content.container,
                     parentDeclPosition, subIter->_parentPosition - subIndex)))
            { table.solve(*subIter, parentDecl, globals);
              ++subIter; ++subIndex;
            };
            if (subIter == subIterEnd)
              break;
          };
          subList = subList->next;
        };
        assert(subIter == subIterEnd);
      };

      globals.add(_waitingSubClassDecl);
      _waitingSubClassDecl = NULL;
      _subGenerations.clear();
      return true;
    };
  }
  else {
    std::vector<const clang::Decl*>::iterator iterEnd
        = _additionalWaitDeclarations.end();
    bool hasFound = false;
    for (std::vector<const clang::Decl*>::iterator
        iter = _additionalWaitDeclarations.begin(); iter != iterEnd; ++iter) {
      if (*iter == decl) {
        _additionalWaitDeclarations.erase(iter);
        hasFound = true;
        break;
      };
    };
    if (hasFound);
      return false;
  };

  class_decl* parentDecl = &_waitingSubClassDecl;
  /* class_decl */ list* parentDeclList = NULL;
  int parentDeclPosition = 0;
  std::set<const clang::Decl*>::iterator
    found = _subWaitDeclarations.find(decl);
  assert(found != _subWaitDeclarations.end());
  std::vector<MissingSubClassGeneration>::iterator
    subIterEnd = _subGenerations.end();
  int subIndex = 0;
  for (std::vector<MissingSubClassGeneration>::iterator
      subIter = _subGenerations.begin(); subIter != subIterEnd; ) {
    if (subIter->removeWaitWithinClass(decl, parentDeclList,
        (/* class_decl */ list*)
          &(*parentDecl)->cons_class_decl.CCompound.body->content.container,
        parentDeclPosition, subIter->_parentPosition - subIndex)) {
      _subGenerations.erase(subIter);
      if (_subGenerations.empty()) {
        assert(_subWaitDeclarations.size() == 1);
        _subWaitDeclarations.clear();
        return _additionalWaitDeclarations.empty();
      };
      subIterEnd = _subGenerations.end();
    }
    else
      ++subIter;
    ++subIndex;
  }
  _subWaitDeclarations.erase(found);
  return false;
}

#endif

void
VisitTable::MissingFunctionGeneration::print(std::ostream& out) const {
  if (_waitingFunDefinition) {
    assert(_waitingFunDefinition->tag_translation_unit_decl == FUNCTION);
    decl_or_impl_name name = _waitingFunDefinition
      ->cons_translation_unit_decl.Function.fun_name;
    if (name->tag_decl_or_impl_name == DECLARATION)
      out << "non-generated method " << name->cons_decl_or_impl_name
        .Declaration.name << ": ";
    else {
      out << "non-generated function ";
      /* qualification */ list prequalification = name
          ->cons_decl_or_impl_name.Implementation.name->prequalification;
      while (prequalification) {
        qualification qual = (qualification) prequalification->element
            .container;
        if (qual->tag_qualification == QNAMESPACE)
          out << qual->cons_qualification.QNamespace.name;
        else if (qual->tag_qualification == QSTRUCTORCLASS)
          out << qual->cons_qualification.QStructOrClass.name;
        else {
           assert(qual->tag_qualification == QTEMPLATEINSTANCE);
           out << qual->cons_qualification.QTemplateInstance.name
               << "<...>";
        };
        out << "::";
        prequalification = prequalification->next;
      };
      out << name->cons_decl_or_impl_name.Implementation.name->decl_name;
      out << ": ";
    };
  }
  else {
    out << "non-generated function symbol ";
    KeyInfo::print(out);
  }
  if (!_waitDeclarations.empty()) {
    out << "waiting for ";
    std::vector<const clang::Decl*>::const_iterator
      iterEnd = _waitDeclarations.end(), iter = _waitDeclarations.begin();
    while (iter != iterEnd) {
      const clang::NamedDecl* decl = llvm::dyn_cast<clang::NamedDecl>
          (*iter);
      if (decl)
        out << decl->getNameAsString();
      else
        out << "clang_unnamed";
      ++iter;
      if (iter != iterEnd)
        out << ", ";
    };
  };
}

bool
VisitTable::MissingFunctionGeneration::solve(const clang::Decl* decl,
    ForwardReferenceList& globals, VisitTable& table)
{ assert(_waitingFunDefinition);
  bool result = _waitDeclarations.size() == 1;
  if (result) {
    assert(*_waitDeclarations.begin() == decl);
    globals.insertContainer(_waitingFunDefinition);
    if (_waitingAdditionalFunDefinition) {
      globals.insertContainer(_waitingAdditionalFunDefinition);
      _waitingAdditionalFunDefinition = NULL;
    };
    _waitDeclarations.clear();
    _waitingFunDefinition = NULL;
    return result;
  }
  else {
    std::vector<const clang::Decl*>::iterator iterEnd = _waitDeclarations.end();
    bool hasFound = false;
    for (std::vector<const clang::Decl*>::iterator
        iter = _waitDeclarations.begin(); iter != iterEnd; ++iter) {
      if (*iter == decl) {
        _waitDeclarations.erase(iter);
        hasFound = true;
        break;
      };
    };
    assert(hasFound);
  };
  return result;
}

bool
VisitTable::MissingFunctionGeneration::replaceWaitingBy(
    const clang::Decl* oldDecl, const std::vector<const clang::Decl*>& newDecls)
{ { std::vector<const clang::Decl*>::iterator iterEnd
      = _waitDeclarations.end();
    bool hasFound = false;
    std::vector<const clang::Decl*>::iterator
      iter = _waitDeclarations.begin();
    while (!hasFound && iter != iterEnd) {
      if ((hasFound = (*iter) == oldDecl) == false)
         ++iter;
    };
    assert(hasFound);
    _waitDeclarations.erase(iter);
  };
  int targetSize = _waitDeclarations.size();
  const clang::FunctionDecl* functionKey
      = llvm::dyn_cast<clang::FunctionDecl>(key());
  assert(functionKey);
  clang::Decl::Kind kindDecl = functionKey->getDeclContext()->getDeclKind();
  const clang::RecordDecl* parentDecl = 
    (kindDecl>=clang::Decl::firstRecord && kindDecl<=clang::Decl::lastRecord)
      ? static_cast<const clang::RecordDecl*>(functionKey->getDeclContext())
      : NULL;
  std::vector<const clang::Decl*>::const_iterator sourceIterEnd
      = newDecls.end();
  for (std::vector<const clang::Decl*>::const_iterator sourceIter
      = newDecls.begin(); sourceIter != sourceIterEnd; ++sourceIter) {
    if (functionKey && *sourceIter != parentDecl) {
      bool hasFound = false;
      for (int targetIndex = 0; !hasFound && targetIndex < targetSize; 
          ++targetIndex)
        hasFound = *sourceIter == _waitDeclarations[targetIndex];
      if (!hasFound)
        _waitDeclarations.push_back(*sourceIter);
    };
  };
  return _waitDeclarations.size() > 0;
}

void
VisitTable::MissingClassGeneration::print(std::ostream& out) const {
  if (_waitingClassDeclaration) {
    assert(_waitingClassDeclaration->tag_translation_unit_decl==COMPOUND);
    decl_or_impl_name name = _waitingClassDeclaration
      ->cons_translation_unit_decl.Compound.name;
    if (name->tag_decl_or_impl_name == DECLARATION)
      out << "non-generated class " << name->cons_decl_or_impl_name
        .Declaration.name << ": ";
    else {
      out << "non-generated extern class ";
      /* qualification */ list prequalification = name
          ->cons_decl_or_impl_name.Implementation.name->prequalification;
      while (prequalification) {
        qualification qual = (qualification) prequalification->element
            .container;
        if (qual->tag_qualification == QNAMESPACE)
          out << qual->cons_qualification.QNamespace.name;
        else if (qual->tag_qualification == QSTRUCTORCLASS)
          out << qual->cons_qualification.QStructOrClass.name;
        else {
           assert(qual->tag_qualification == QTEMPLATEINSTANCE);
           out << qual->cons_qualification.QTemplateInstance.name
               << "<...>";
        };
        out << "::";
        prequalification = prequalification->next;
      };
      out << name->cons_decl_or_impl_name.Implementation.name->decl_name;
      out << ": ";
    };
  }
  else {
    out << "non-generated class symbol ";
    KeyInfo::print(out);
  };
  if (!_waitDeclarations.empty()) {
    out << "waiting for ";
    std::vector<const clang::Decl*>::const_iterator
      iterEnd = _waitDeclarations.end(), iter = _waitDeclarations.begin();
    while (iter != iterEnd) {
      const clang::NamedDecl* decl = llvm::dyn_cast<clang::NamedDecl>
          (*iter);
      if (decl)
        out << decl->getNameAsString();
      else
        out << "clang_unnamed";
      ++iter;
      if (iter != iterEnd)
        out << ", ";
    };
  };
  if (!_subGenerations.empty()) {
    std::vector<MissingSubClassGeneration>::const_iterator
      iterEnd = _subGenerations.end(), iter = _subGenerations.begin();
    for (; iter != iterEnd; ++iter) {
      out << '\n';
      iter->print(out, 1);
    };
  };
}

bool
VisitTable::MissingClassGeneration::solve(const clang::Decl* decl,
    ForwardReferenceList& globals, VisitTable& table)
{ assert(_waitingClassDeclaration);
  bool result = _waitDeclarations.size() == 1;
  if (result) {
    if (*_waitDeclarations.begin() == decl) {
      globals.insertContainer(_waitingClassDeclaration);

      std::vector<MissingSubClassGeneration>::iterator subIterEnd
          = _subGenerations.end();
      std::vector<MissingSubClassGeneration>::iterator subIter
          = _subGenerations.begin();
      /* class_decl */ list* parentDeclList = NULL;
      int parentDeclPosition = 0;
      int subIndex = 0;
      assert(_subGenerations.empty()
        || (_waitingClassDeclaration->tag_translation_unit_decl == COMPOUND
          && _waitingClassDeclaration->cons_translation_unit_decl
              .Compound.body->is_some));
      while (subIter != subIterEnd && (!subIter->_waitingSubClassDecl
          || subIter->removeWaitWithinClass(decl, parentDeclList,
               (/* class_decl */ list*) &_waitingClassDeclaration
                 ->cons_translation_unit_decl.Compound.body->content.container,
               parentDeclPosition, subIter->_parentPosition - subIndex))) {
        table.solve(*subIter, *this, globals);
        ++subIter; ++subIndex;
      };
      if (subIter != subIterEnd) {
        // [TODO] use parentDeclList and subIter->_parentPosition
        //   instead of a new list.
        /* class_decl */ list subList = (list) _waitingClassDeclaration
            ->cons_translation_unit_decl.Compound.body->content.container;
        assert(subList);
        while (subList) {
          class_decl classElement = (class_decl) subList->element.container;
          bool isEqual = classElement == subIter->_waitingSubClassDecl;
          if (!isEqual)
            isEqual = classElement->tag_class_decl == CCOMPOUND
              && subIter->_waitingSubClassDecl->tag_class_decl == CCOMPOUND
              && !strcmp(classElement->cons_class_decl.CCompound.name,
                  subIter->_waitingSubClassDecl->cons_class_decl.CCompound.name)
              && tkind_equal(
                  classElement->cons_class_decl.CCompound.template_kind,
                  subIter->_waitingSubClassDecl->cons_class_decl
                    .CCompound.template_kind);
          if (isEqual) {
            table.addWaitFor(*subIter, subIter->_waitingSubClassDecl, this,
              globals, classElement!=subIter->_waitingSubClassDecl
              /* shouldBeSubkey */);
            ++subIter; ++subIndex;
            while (subIter != subIterEnd && (!subIter->_waitingSubClassDecl
                || subIter->removeWaitWithinClass(decl, parentDeclList,
                     (/* class_decl */ list*) &_waitingClassDeclaration
                       ->cons_translation_unit_decl.Compound
                         .body->content.container, parentDeclPosition,
                     subIter->_parentPosition - subIndex))) {
              table.solve(*subIter, *this, globals);
              ++subIter; ++subIndex;
            };
            if (subIter == subIterEnd)
              break;
          };
          subList = subList->next;
        };
        assert(subIter == subIterEnd);
      };

      _waitingClassDeclaration = NULL;
      _subGenerations.clear();
      return true;
    };
  }
  else {
    std::vector<const clang::Decl*>::iterator iterEnd = _waitDeclarations.end();
    bool hasFound = false;
    for (std::vector<const clang::Decl*>::iterator
        iter = _waitDeclarations.begin(); iter != iterEnd; ++iter) {
      if (*iter == decl) {
        _waitDeclarations.erase(iter);
        hasFound = true;
        break;
      };
    };
    if (hasFound)
      return false;
  };

  translation_unit_decl* parentDecl = &_waitingClassDeclaration;
  /* class_decl */ list* parentDeclList = NULL;
  int parentDeclPosition = 0;
  std::set<const clang::Decl*>::iterator
    found = _subWaitDeclarations.find(decl);
  assert(found != _subWaitDeclarations.end());
  std::vector<MissingSubClassGeneration>::iterator
    subIterEnd = _subGenerations.end();
  int subIndex = 0;
  for (std::vector<MissingSubClassGeneration>::iterator
      subIter = _subGenerations.begin(); subIter != subIterEnd; ) {
    if (subIter->removeWaitWithinClass(decl, parentDeclList,
        (/* class_decl */ list*) &(*parentDecl)
          ->cons_translation_unit_decl.Compound.body->content.container,
        parentDeclPosition, subIter->_parentPosition - subIndex)) {
      _subGenerations.erase(subIter);
      if (_subGenerations.empty()) {
        assert(_subWaitDeclarations.size() == 1);
        _subWaitDeclarations.clear();
        return _waitDeclarations.empty();
      };
      subIterEnd = _subGenerations.end();
    }
    else
      ++subIter;
    ++subIndex;
  }
  _subWaitDeclarations.erase(found);
  return false;
}

void
VisitTable::MissingClassGeneration::removeSubWait(const clang::Decl* decl) {
  std::set<const clang::Decl*>::iterator
    found = _subWaitDeclarations.find(decl);
  if (found != _subWaitDeclarations.end()) {
    /* class_decl */ list* parentDeclList = NULL;
    int parentDeclPosition = 0;
    std::vector<MissingSubClassGeneration>::iterator
      subIterEnd = _subGenerations.end();
    int subIndex = 0;
    for (std::vector<MissingSubClassGeneration>::iterator
        subIter = _subGenerations.begin(); subIter != subIterEnd; ) {
      if (!subIter->_waitingSubClassDecl ||
        subIter->removeWaitWithinClass(decl, parentDeclList,
          (/* class_decl */ list*) &_waitingClassDeclaration
            ->cons_translation_unit_decl.Compound.body->content.container,
          parentDeclPosition, subIter->_parentPosition - subIndex)) {
        _subGenerations.erase(subIter);
        if (_subGenerations.empty()) {
          assert(_subWaitDeclarations.size() == 1);
          _subWaitDeclarations.clear();
          return;
        };
        subIterEnd = _subGenerations.end();
      }
      else
        ++subIter;
      ++subIndex;
    }
    _subWaitDeclarations.erase(found);
  };
}

bool
VisitTable::MissingClassGeneration::replaceWaitingBy(const clang::Decl* oldDecl,
    const std::vector<const clang::Decl*>& newDecls) {
  bool hasFoundInMain = false;
  { std::vector<const clang::Decl*>::iterator
      iterEnd = _waitDeclarations.end(), iter = _waitDeclarations.begin();
    while(!hasFoundInMain && iter != iterEnd)
      if ((hasFoundInMain = (*iter) == oldDecl) == false)
        ++iter;
    if (hasFoundInMain)
      _waitDeclarations.erase(iter);
  };
  if (hasFoundInMain) {
    int targetSize = _waitDeclarations.size();
    std::vector<const clang::Decl*>::const_iterator sourceIterEnd
        = newDecls.end();
    for (std::vector<const clang::Decl*>::const_iterator sourceIter
        = newDecls.begin(); sourceIter != sourceIterEnd; ++sourceIter) {
      bool hasFound = false;
      for (int targetIndex = 0; !hasFound && targetIndex < targetSize; 
          ++targetIndex)
        hasFound = *sourceIter == _waitDeclarations[targetIndex];
      if (!hasFound)
        _waitDeclarations.push_back(*sourceIter);
    };
  }
  else {
    std::set<const clang::Decl*>::iterator found = _subWaitDeclarations
      .find(oldDecl);
    assert(found != _subWaitDeclarations.end());
    _subWaitDeclarations.erase(found);
    { std::vector<const clang::Decl*>::const_iterator sourceIterEnd
        = newDecls.end();
      for (std::vector<const clang::Decl*>::const_iterator sourceIter
          = newDecls.begin(); sourceIter != sourceIterEnd; ++sourceIter)
        _subWaitDeclarations.insert(*sourceIter);
    };
    std::vector<MissingSubClassGeneration>::iterator
        subIterEnd = _subGenerations.end();
    for (std::vector<MissingSubClassGeneration>::iterator subIter
        = _subGenerations.begin(); subIter != subIterEnd; ++subIter)
      subIter->replaceWaitingBy(oldDecl, newDecls);
  }
  return true;
}

void
VisitTable::MissingDecl::print(std::ostream& out) const {
  out << "missing declaration: ";
  KeyInfo::print(out);
  if (!_waitingDecls.empty()) {
    WaitingDecls::const_iterator iterEnd = _waitingDecls.end(),
      iter = _waitingDecls.begin();
    out << "expected by\n";
    while (iter != iterEnd) {
      out << "\t- ";
      (*iter)->print(out);
      ++iter;
      if (iter != iterEnd)
        out << '\n';
    };
  };
}

translation_unit_decl
VisitTable::globalizeDecl(const clang::NamedDecl* decl,
    class_decl classElement) const {
  translation_unit_decl result;
  if (classElement->tag_class_decl == CMETHOD) {
    /* statement list */ option body;
    tkind templateParameters = classElement->cons_class_decl.CMethod
        .template_kind;
    classElement->cons_class_decl.CMethod.template_kind = tkind_TStandard();
    if (classElement->cons_class_decl.CMethod.body->is_some) {
      body = opt_some_container((list) classElement->cons_class_decl.CMethod
          .body->content.container);
      free(classElement->cons_class_decl.CMethod.body);
      classElement->cons_class_decl.CMethod.body = opt_none();
    }
    else
      body = opt_none();
    /* arg_decl */ list args = classElement->cons_class_decl.CMethod.args;
    classElement->cons_class_decl.CMethod.args = NULL;
    /* function_contract */ option spec = classElement->cons_class_decl
        .CMethod.fun_spec;
    classElement->cons_class_decl.CMethod.fun_spec = opt_none();

    result = translation_unit_decl_Function(
      decl_or_impl_name_Implementation(_clangUtils->makeQualifiedName(*decl)),
      funkind_dup(classElement->cons_class_decl.CMethod.kind),
      copy_loc(classElement->cons_class_decl.CMethod.loc),
      qual_type_dup(classElement->cons_class_decl.CMethod
        .return_type), args, body, false /* is_extern_c */,
      false /* ghost: TODO: refine that for ghost classes. */,
      classElement->cons_class_decl.CMethod.is_variadic, templateParameters,
       true /* has_further_definition */,
       opt_none() /* throws */,
       spec);
  }
  else if (classElement->tag_class_decl == CCOMPOUND) {
    /* class_decl list */ option body;
    tkind templateParameters = classElement->cons_class_decl.CCompound
        .template_kind;
    classElement->cons_class_decl.CCompound.template_kind = tkind_TStandard();
    if (classElement->cons_class_decl.CCompound.body->is_some) {
      body = opt_some_container((list) classElement->cons_class_decl.CCompound
          .body->content.container);
      free(classElement->cons_class_decl.CCompound.body);
      classElement->cons_class_decl.CCompound.body = opt_none();
    }
    else
      body = opt_none();
    /* inheritance list */ option inheritanceList
      = classElement->cons_class_decl.CCompound.inherits;
    classElement->cons_class_decl.CCompound.inherits = opt_none();
    result =
      translation_unit_decl_Compound(
        copy_loc(classElement->cons_class_decl.CCompound.loc),
        decl_or_impl_name_Implementation(_clangUtils->makeQualifiedName(*decl)),
        classElement->cons_class_decl.CCompound.kind, inheritanceList, body,
        classElement->cons_class_decl.CCompound.has_virtual,
        templateParameters, false /*is_extern_c_context*/, false /* ghost */);
  }
  else
    assert(false);
  free_class_decl(classElement);
  return result;
}

void
VisitTable::solve(MissingSubClassGeneration& classDecl,
    MissingClassGeneration& rootDecl,
    ForwardReferenceList& globals) {
  assert(!classDecl._waitingSubClassDecl
      && classDecl._additionalWaitDeclarations.empty());
  std::vector<MissingSubClassGeneration>::iterator subIterEnd
      = classDecl._subGenerations.end();
  std::vector<MissingSubClassGeneration>::iterator subIter
      = classDecl._subGenerations.begin();
  while (subIter != subIterEnd && !subIter->_waitingSubClassDecl) {
    solve(*subIter, rootDecl, globals);
    ++subIter;
  };
  if (subIter != subIterEnd) {
    assert(classDecl._waitingSubClassDecl->tag_class_decl == CCOMPOUND &&
      classDecl._waitingSubClassDecl->cons_class_decl.CCompound.body->is_some);
    /* class_decl */ list subList = (list) classDecl._waitingSubClassDecl
        ->cons_class_decl.CCompound.body->content.container;
    assert(subList);
    while (subList) {
      class_decl classElement = (class_decl) subList->element.container;
      bool isEqual = classElement == subIter->_waitingSubClassDecl;
      if (!isEqual)
        isEqual = classElement->tag_class_decl == CCOMPOUND
          && subIter->_waitingSubClassDecl->tag_class_decl == CCOMPOUND
          && !strcmp(classElement->cons_class_decl.CCompound.name,
              subIter->_waitingSubClassDecl->cons_class_decl.CCompound.name)
          && tkind_equal(
              classElement->cons_class_decl.CCompound.template_kind,
              subIter->_waitingSubClassDecl->cons_class_decl
                .CCompound.template_kind);
      if (isEqual) {
        addWaitFor(*subIter, subIter->_waitingSubClassDecl, &rootDecl,
          globals, classElement != subIter->_waitingSubClassDecl
          /* shouldBeSubkey */);
        ++subIter;
        while (subIter != subIterEnd && !subIter->_waitingSubClassDecl) {
          solve(*subIter, rootDecl, globals);
          ++subIter;
        };
        if (subIter == subIterEnd)
          break;
      };
      subList = subList->next;
    };
    assert(subIter == subIterEnd);
  };

  KeyInfo locateKey(classDecl._key);
  ContentTable::iterator found = _content.find(&locateKey);
  if (found != _content.end() && (*found)->isMissingDecl()) {
    MissingDecl* waitingForDecl = (MissingDecl*) *found;
    MissingDecl::WaitingDecls::iterator iterEnd
      = waitingForDecl->waitingDecls().end();
    for (MissingDecl::WaitingDecls::iterator iter
        = waitingForDecl->waitingDecls().begin(); iter != iterEnd; ++iter) {
      if ((*iter)->solve(classDecl._key, globals, *this)) {
        KeyInfo* toDelete = *iter;
        *iter = new KeyInfo(**iter);
        delete toDelete;
      };
    };
    KeyInfo* toDelete = waitingForDecl;
    _content.erase(found);
    _content.insert(new KeyInfo(classDecl._key));
    delete toDelete;
  };
}

void
VisitTable::addWaitFor(MissingSubClassGeneration& classDecl,
    class_decl classElement, MissingClassGeneration* parentDecl,
    ForwardReferenceList& globals, bool shouldBeSubkey)
{ assert(classDecl._waitingSubClassDecl
      && !classDecl._additionalWaitDeclarations.empty());
  KeyInfo* missingGeneration = NULL;
  std::vector<const clang::Decl*>* waitDeclarations = NULL;
  bool shouldPreempt = false;

  if (classElement->tag_class_decl == CMETHOD) {
    assert(classElement->cons_class_decl.CMethod.body->is_some);
    assert(!shouldBeSubkey);
    /* statement */ list body = (list) classElement->cons_class_decl.CMethod
        .body->content.container;
    free(classElement->cons_class_decl.CMethod.body);
    classElement->cons_class_decl.CMethod.body = opt_none();
    assert(llvm::dyn_cast<clang::NamedDecl>(classDecl._key));
    /* arg_decl */ list copyArgs = NULL;
    /* arg_decl */ list& endCopyArgs = copyArgs;
    /* arg_decl */ list iterArgs = classElement->cons_class_decl.CMethod.args;
    while (iterArgs) {
      endCopyArgs = cons_container(arg_decl_dup((arg_decl)
            iterArgs->element.container), NULL);
      endCopyArgs = endCopyArgs->next;
      iterArgs = iterArgs->next;
    };
    /* function_contract */ option spec = classElement->cons_class_decl
        .CMethod.fun_spec;
    classElement->cons_class_decl.CMethod.fun_spec = opt_none();

    assert(llvm::dyn_cast<clang::FunctionDecl>(classDecl._key));
    tkind templateParameters = tkind_dup(classElement->cons_class_decl.CMethod
        .template_kind);
    MissingFunctionGeneration* insertion = new MissingFunctionGeneration(
      static_cast<const clang::FunctionDecl*>(classDecl._key),
      translation_unit_decl_Function(
        decl_or_impl_name_Implementation(_clangUtils->makeQualifiedName(
          *static_cast<const clang::NamedDecl*>(classDecl._key))),
        funkind_dup(classElement->cons_class_decl.CMethod.kind),
        copy_loc(classElement->cons_class_decl.CMethod.loc),
        qual_type_dup(classElement->cons_class_decl.CMethod
          .return_type), copyArgs, opt_some_container(body), 
        false /* is_extern_c */,
        false /* ghost */,
        classElement->cons_class_decl.CMethod.is_variadic, templateParameters,
        false /* has_further_definition */,
        opt_none() /* throws */,
        spec));
    insertion->_waitDeclarations.swap(classDecl._additionalWaitDeclarations);
    missingGeneration = insertion;
    waitDeclarations = &insertion->_waitDeclarations;
  }
  else if (classElement->tag_class_decl == CCOMPOUND) {
    assert(classElement->cons_class_decl.CCompound.body->is_some);
    /* class_decl */ list body = (list) classElement->cons_class_decl.CCompound
        .body->content.container;
    free(classElement->cons_class_decl.CCompound.body);
    classElement->cons_class_decl.CCompound.body = opt_none();
    tkind templateParameters = classElement->cons_class_decl
        .CCompound.template_kind;
    classElement->cons_class_decl.CCompound.template_kind = tkind_TStandard();
    assert(llvm::dyn_cast<clang::NamedDecl>(classDecl._key));
    /* inheritance list */ option inheritanceList
      = classElement->cons_class_decl.CCompound.inherits;
    classElement->cons_class_decl.CCompound.inherits = opt_none();
    
    assert(llvm::dyn_cast<clang::RecordDecl>(classDecl._key));
    MissingClassGeneration* insertion = new MissingClassGeneration(
      static_cast<const clang::RecordDecl*>(classDecl._key),
      translation_unit_decl_Compound(
        copy_loc(classElement->cons_class_decl.CCompound.loc),
        decl_or_impl_name_Implementation(_clangUtils->makeQualifiedName(
          *static_cast<const clang::NamedDecl*>(classDecl._key))),
        classElement->cons_class_decl.CCompound.kind,
        inheritanceList, opt_some_container(body),
        classElement->cons_class_decl.CCompound.has_virtual,
        templateParameters, false /* is_extern_c_context */, false /*ghost*/));
    insertion->_waitDeclarations.swap(classDecl._additionalWaitDeclarations);
    insertion->_subGenerations.swap(classDecl._subGenerations);
    insertion->_subWaitDeclarations.swap(classDecl._subWaitDeclarations);
    missingGeneration = insertion;
    waitDeclarations = &insertion->_waitDeclarations;
    shouldPreempt = true;
  }
  else
    assert(false);

  assert(missingGeneration && waitDeclarations);
  KeyInfo locateKey(classDecl._key);
  ContentTable::iterator found = _content.lower_bound(&locateKey);
  if (found == _content.end() || KeyInfo::Less()(*found, &locateKey))
    found = _content.insert(found, missingGeneration);
  else {
    KeyInfo* toDelete;
    if (!shouldBeSubkey) {
      assert((*found)->isMissingDecl());
      MissingDecl* waitingForDecl = (MissingDecl*) *found;
      MissingDecl::WaitingDecls::iterator iterEnd
        = waitingForDecl->waitingDecls().end();
      for (MissingDecl::WaitingDecls::iterator iter
          = waitingForDecl->waitingDecls().begin(); iter != iterEnd; ++iter) {
        if ((*iter)->solve(classDecl._key, globals, *this)) {
          toDelete = *iter;
          *iter = new KeyInfo(**iter);
          delete toDelete;
        };
      };
      toDelete = waitingForDecl;
    }
    else {
      assert((*found)->isSubKey());
      toDelete = *found;
    }
    _content.erase(found);
    _content.insert(missingGeneration);
    delete toDelete;
  };

  // update the MissingDecl to enable solving notifications.
  std::vector<const clang::Decl*>::const_iterator endWaitIterEnd
    = waitDeclarations->end();
  for (std::vector<const clang::Decl*>::const_iterator endWaitIter
        = waitDeclarations->begin();
      endWaitIter != endWaitIterEnd; ++endWaitIter) {
    KeyInfo locateDecl(*endWaitIter);
    ContentTable::iterator found = _content.find(&locateDecl);
    if (found == _content.end()) {
      assert(shouldBeSubkey);
      MissingDecl* newMissing = new MissingDecl(*endWaitIter);
      _content.insert(newMissing);
      newMissing->waitingDecls().push_back(missingGeneration);
    }
    else if ((*found)->isMissingDecl()) {
      { std::vector<KeyInfo*>::iterator
           locateIter = ((MissingDecl&) **found).waitingDecls().begin(),
           locateIterEnd = ((MissingDecl&) **found).waitingDecls().end();
        bool hasFound = false;
        for (; !hasFound && locateIter != locateIterEnd; ++locateIter) {
          if (*locateIter == parentDecl) {
            hasFound = true;
            ((MissingDecl&) **found).waitingDecls().erase(locateIter);
          }
        };
      };
      // see enableNotificationFromBeforeReplaceWaiting that has not been
      //   called by MissingSubClassGeneration::setAsComplete
      if (!shouldPreempt)
        ((MissingDecl&) **found).waitingDecls().push_back(missingGeneration);
      else {
        std::vector<KeyInfo*>::iterator
           locateIter = ((MissingDecl&) **found).waitingDecls().begin(),
           locateIterEnd = ((MissingDecl&) **found).waitingDecls().end();
        // [TODO] may happen: function other subclass subclass
        //                    where function depends on subclass
        for (; locateIter != locateIterEnd; ++locateIter) {
          if ((*locateIter)->isFunctionGenerationMissing()
              && ((const clang::FunctionDecl*)
                     (*locateIter)->key())->getParent()
                == ((const clang::RecordDecl*)
                     missingGeneration->key())->getParent())
            break;
        }
        if (locateIter != locateIterEnd)
          ((MissingDecl&) **found).waitingDecls().insert(locateIter,
            missingGeneration);
        else
          ((MissingDecl&) **found).waitingDecls().push_back(missingGeneration);
      }
    }
    else if ((*found)->isInstanceClass()) {
      if (((InstanceClassGeneration*) *found)->_waitingDecls.empty()
          || ((InstanceClassGeneration*) *found)->_waitingDecls.back()
               !=missingGeneration) {
        { std::vector<KeyInfo*>::iterator locateIter
               = ((InstanceClassGeneration&) **found)._waitingDecls.begin(),
             locateIterEnd
               = ((InstanceClassGeneration&) **found)._waitingDecls.end();
          bool hasFound = false;
          for (; !hasFound && locateIter != locateIterEnd; ++locateIter) {
            if (*locateIter == parentDecl) {
              hasFound = true;
              ((InstanceClassGeneration&) **found)._waitingDecls
                .erase(locateIter);
            }
          };
        };
        ((InstanceClassGeneration*) *found)
          ->_waitingDecls.push_back(missingGeneration);
      };
    }
    else { // should not occur
      assert(false);
    }
  };
}

void
VisitTable::addDeclaration(const clang::Decl* decl,
    ForwardReferenceList& globals) {
  KeyInfo locateKey(decl);
  ContentTable::iterator found = _content.lower_bound(&locateKey);
  if (found != _content.end() && (*found)->_key == decl) {
    assert((*found)->isMissingDecl() || !(*found)->isGenerationMissing());
    if (!(*found)->isMissingDecl())
      return;
    MissingDecl* waitingForDecl = (MissingDecl*) *found;
    MissingDecl::WaitingDecls::iterator iterEnd
      = waitingForDecl->waitingDecls().end();
    KeyInfo* toDelete = waitingForDecl;
    _content.erase(found);
    for (MissingDecl::WaitingDecls::iterator iter = waitingForDecl
        ->waitingDecls().begin(); iter != iterEnd; ++iter) {
      if ((*iter)->solve(decl, globals, *this)) {
        KeyInfo* toLocalDelete = *iter;
        ContentTable::iterator localFound = _content.find(toLocalDelete);
        assert(localFound != _content.end() && *localFound == toLocalDelete);
        _content.erase(localFound);
        *iter = new KeyInfo(**iter);
        _content.insert(*iter);
        delete toLocalDelete;
      };
    };
    _content.insert(new KeyInfo(decl));
    delete toDelete;
  }
  else
    _content.insert(new KeyInfo(decl));
}

void
VisitTable::enableNotificationFromBeforeReplaceWaiting(
    std::vector<const clang::Decl*>& dependencies,
    const std::vector<KeyInfo*>& waitingDecls,
    KeyInfo* originDependencies, bool mayHaveInstanceClass) {
  std::vector<const clang::Decl*>::iterator
    absentIterEnd = dependencies.end();
  for (std::vector<const clang::Decl*>::iterator
      absentIter = dependencies.begin();
      absentIter != absentIterEnd; ++absentIter) {
    KeyInfo locateKey(*absentIter);
    ContentTable::const_iterator found = _content.find(&locateKey);
    if (found == _content.end()) {
      MissingDecl* newMissing = new MissingDecl(*absentIter);
      _content.insert(newMissing);
      if (originDependencies)
        newMissing->_waitingDecls.push_back(originDependencies);
      newMissing->_waitingDecls.insert(newMissing->_waitingDecls.end(),
        waitingDecls.begin(), waitingDecls.end());
    }
    else if ((*found)->isMissingDecl()) { // has locally been found after
      MissingDecl* newMissing = (MissingDecl*) *found;
      std::vector<KeyInfo*>::const_iterator
        iterSourceEnd = waitingDecls.end();
      int sizeTarget = newMissing->_waitingDecls.size();
      if (originDependencies)
        newMissing->_waitingDecls.push_back(originDependencies);
      for (std::vector<KeyInfo*>::const_iterator iterSource
            = waitingDecls.begin(); iterSource != iterSourceEnd; ++iterSource) {
        bool hasFound = false;
        int foundIndex = 0;
        for (int indexTarget = 0; !hasFound && indexTarget < sizeTarget;
            ++indexTarget) {
          if (*iterSource == newMissing->_waitingDecls[indexTarget]) {
            hasFound = true;
            foundIndex = indexTarget;
          }
        };
        if (hasFound) { // the method soon depends from newMissing
          // but the generation of the method should occur after the class!
          newMissing->_waitingDecls.erase(
            newMissing->_waitingDecls.begin() + foundIndex);
        }
        newMissing->_waitingDecls.push_back(*iterSource);
      };
    }
    else if (mayHaveInstanceClass && (*found)->isInstanceClass()) {
      InstanceClassGeneration* newMissing = (InstanceClassGeneration*) *found;
      std::vector<KeyInfo*>::const_iterator
        iterSourceEnd = waitingDecls.end();
      int sizeTarget = newMissing->_waitingDecls.size();
      if (originDependencies)
        newMissing->_waitingDecls.push_back(originDependencies);
      for (std::vector<KeyInfo*>::const_iterator iterSource
            = waitingDecls.begin(); iterSource != iterSourceEnd; ++iterSource) {
        bool hasFound = false;
        int foundIndex = 0;
        for (int indexTarget = 0; !hasFound && indexTarget < sizeTarget;
            ++indexTarget) {
          if (*iterSource == newMissing->_waitingDecls[indexTarget]) {
            hasFound = true;
            foundIndex = indexTarget;
          }
        };
        if (hasFound) { // the method soon depends from newMissing
          // but the generation of the method should occur after the class!
          newMissing->_waitingDecls.erase(
            newMissing->_waitingDecls.begin() + foundIndex);
        }
        newMissing->_waitingDecls.push_back(*iterSource);
      };
    }
    else { // should not occur
       int index = absentIter - dependencies.begin();
       dependencies.erase(absentIter);
       absentIter =  dependencies.begin() + index - 1;
       absentIterEnd =  dependencies.end();
    };
  }
}

void
VisitTable::addFunctionDeclaration(const clang::FunctionDecl* decl,
    ForwardReferenceList& globals) {
  clang::Decl::Kind parentKind = decl->getDeclContext()->getDeclKind();
  std::vector<const clang::Decl*> parentDependencies;
  if (parentKind >= clang::Decl::firstRecord
      && parentKind <= clang::Decl::lastRecord)
    ensureGeneration(static_cast<const clang::RecordDecl*>
        (decl->getDeclContext()), parentDependencies);

  KeyInfo locateKey(decl);
  ContentTable::iterator found = _content.lower_bound(&locateKey);
  if (found != _content.end() && (*found)->_key == decl) {
    assert((*found)->isMissingDecl() || !(*found)->isGenerationMissing());
    if (!(*found)->isMissingDecl())
      return;
    MissingDecl* waitingForDecl = (MissingDecl*) *found;
    if (!parentDependencies.empty())
      enableNotificationFromBeforeReplaceWaiting(parentDependencies,
          waitingForDecl->_waitingDecls, NULL /* originDependencies */,
          true /* mayHaveInstanceClass */);

    MissingDecl::WaitingDecls::iterator iterEnd
      = waitingForDecl->waitingDecls().end();
    KeyInfo* toDelete = waitingForDecl;
    _content.erase(found);
    for (MissingDecl::WaitingDecls::iterator iter = waitingForDecl
        ->waitingDecls().begin(); iter != iterEnd; ++iter) {
      bool doesSolve = true;
      if (!parentDependencies.empty())
        doesSolve = !(*iter)->replaceWaitingBy(decl, parentDependencies);
      if (doesSolve) {
        if ((*iter)->solve(decl, globals, *this)) {
          KeyInfo* toLocalDelete = *iter;
          ContentTable::iterator localFound = _content.find(toLocalDelete);
          assert(localFound != _content.end() && *localFound == toLocalDelete);
          _content.erase(localFound);
          *iter = new KeyInfo(**iter);
          _content.insert(*iter);
          delete toLocalDelete;
        };
      }
    };
    _content.insert(new KeyInfo(decl));
    delete toDelete;
  }
  else
    _content.insert(new KeyInfo(decl));
}

void
VisitTable::addSubDeclaration(const clang::Decl* decl,
    const clang::Decl* root,
    MissingSubClassGeneration* lastInstance /* should be a stack */,
    ForwardReferenceList& globals) {
  KeyInfo locateKey(decl);
  ContentTable::iterator found = _content.lower_bound(&locateKey);
  if (found != _content.end() && (*found)->_key == decl) {
    assert((*found)->isMissingDecl() || !(*found)->isGenerationMissing());
    if (!(*found)->isMissingDecl())
      return;
    MissingDecl* waitingForDecl = (MissingDecl*) *found;
    MissingDecl::WaitingDecls::iterator iterEnd
      = waitingForDecl->waitingDecls().end();
    KeyInfo* toDelete = waitingForDecl;
    _content.erase(found);
    for (MissingDecl::WaitingDecls::iterator iter = waitingForDecl
        ->waitingDecls().begin(); iter != iterEnd; ++iter) {
      if ((*iter)->solve(decl, globals, *this)) {
        KeyInfo* toLocalDelete = *iter;
        ContentTable::iterator localFound = _content.find(toLocalDelete);
        assert(localFound != _content.end() && *localFound == toLocalDelete);
        _content.erase(localFound);
        *iter = new KeyInfo(**iter);
        _content.insert(*iter);
        delete toLocalDelete;
      };
    };
    delete toDelete;
  };
  SubKeyInfo* subInfo = new SubKeyInfo(decl, root);
  _content.insert(subInfo);
  if (subInfo && lastInstance)
    subInfo->addSpecificWaitDeclarations(lastInstance->waitDeclarations());
}

void
VisitTable::ensureGeneration(const clang::Decl* decl,
    std::vector<const clang::Decl*>& waitedDeclarations) const
{ KeyInfo locateKey(decl);
  ContentTable::const_iterator found = _content.find(&locateKey);
  const clang::Decl* declToInsert = NULL;
  const std::vector<const clang::Decl*>* declsToInsert = NULL;
  const std::vector<const clang::Decl*>* additionalDeclsToInsert = NULL;
  const std::vector<const clang::Decl*>* specificAdditionalDeclsToInsert = NULL;
  if (found == _content.end())
    declToInsert = decl;
  else {
    if ((*found)->isSubKey()) {
      specificAdditionalDeclsToInsert =
        &static_cast<const SubKeyInfo*>(*found)->getSpecificWaitDeclarations();
      KeyInfo locateRootKey(static_cast<const SubKeyInfo*>(*found)->root());
      found = _content.find(&locateRootKey);
      assert(found != _content.end());
      if ((*found)->isClassGenerationMissing())
        additionalDeclsToInsert = ((const MissingClassGeneration*) *found)
          ->findSubClassDependencies(decl);
      decl = locateRootKey.key();
    };
    if ((*found)->isMissingDecl())
      declToInsert = decl;
    else if ((*found)->isGenerationMissing()) {
      if ((*found)->isInstanceClass())
        declToInsert = decl;
      else if ((*found)->isFunctionGenerationMissing()) {
        const MissingFunctionGeneration* functionInfo
            = (const MissingFunctionGeneration*) *found;
        declsToInsert = &functionInfo->waitDeclarations();
      }
      else {
        assert((*found)->isClassGenerationMissing());
        const MissingClassGeneration* classInfo
            = (const MissingClassGeneration*) *found;
        declsToInsert = &classInfo->waitDeclarations();
      };
    };
  };

  if (declToInsert) {
    bool hasFound = false;
    std::vector<const clang::Decl*>::const_iterator
      iterEnd = waitedDeclarations.end(), iter = waitedDeclarations.begin();
    for (; !hasFound && iter != iterEnd; ++iter)
      hasFound = *iter == declToInsert;
    if (!hasFound)
      waitedDeclarations.push_back(declToInsert);
  };
  while (declsToInsert
         || additionalDeclsToInsert || specificAdditionalDeclsToInsert) {
    if (declsToInsert) {
      std::vector<const clang::Decl*>::const_iterator
        sourceIterEnd = declsToInsert->end(),
        sourceIter = declsToInsert->begin();
      for (; sourceIter != sourceIterEnd; ++sourceIter) {
        declToInsert = *sourceIter;
        bool hasFound = false;
        std::vector<const clang::Decl*>::const_iterator
          iterEnd = waitedDeclarations.end(), iter = waitedDeclarations.begin();
        for (; !hasFound && iter != iterEnd; ++iter)
          hasFound = *iter == declToInsert;
        if (!hasFound)
          waitedDeclarations.push_back(declToInsert);
      }
    };
    if (additionalDeclsToInsert) {
      declsToInsert = additionalDeclsToInsert;
      additionalDeclsToInsert = NULL;
    }
    else if (specificAdditionalDeclsToInsert) {
      declsToInsert = specificAdditionalDeclsToInsert;
      specificAdditionalDeclsToInsert = NULL;
    }
    else
      declsToInsert = NULL;
  };
}

VisitTable::MissingClassGeneration&
VisitTable::addInstanceClass(const clang::RecordDecl* decl,
    translation_unit_decl classDecl) {
  KeyInfo locateKey(decl);
  ContentTable::iterator found = _content.lower_bound(&locateKey);
  InstanceClassGeneration* result;
  if (found != _content.end() && (*found)->_key == decl) {
    assert((*found)->isMissingDecl());
    MissingDecl* oldMissing = (MissingDecl*) *found;
    result = new InstanceClassGeneration(decl, classDecl);
    _content.erase(found);
    _content.insert(result);
    result->_waitingDecls.swap(oldMissing->_waitingDecls);
    delete oldMissing;
  }
  else {
    result = new InstanceClassGeneration(decl, classDecl);
    _content.insert(found, result);
  };
  return *result;
}

void
VisitTable::setInstanceClassAsComplete(InstanceClassGeneration* instance,
    ForwardReferenceList& globals) {
  if (!instance->_subGenerations.empty()) {
    std::vector<MissingSubClassGeneration>::const_iterator
      subIterEnd = instance->_subGenerations.end(),
      subIter = instance->_subGenerations.begin();
    for (; subIter != subIterEnd; ++subIter) {
      instance->_subWaitDeclarations.insert(
        subIter->_additionalWaitDeclarations.begin(),
        subIter->_additionalWaitDeclarations.end());
      instance->_subWaitDeclarations.insert(
        subIter->_subWaitDeclarations.begin(),
        subIter->_subWaitDeclarations.end());
    };
  };
  int absentSize = instance->_waitDeclarations.size();
  for (int absentIndex = absentSize-1; absentIndex >= 0; --absentIndex) {
    const clang::Decl* decl = instance->_waitDeclarations[absentIndex];
    if (decl == instance->key()) {
      instance->_waitDeclarations.erase(instance->_waitDeclarations.begin()
          + absentIndex);
      instance->removeSubWait(decl);
    }
    else {
      KeyInfo locateKey(decl);
      ContentTable::const_iterator found = _content.find(&locateKey);
      if (found != _content.end() && !(*found)->isMissingDecl()) {
        if ((*found)->isGenerationMissing())
          assert(!(*found)->isInstanceClass());
        else {
          instance->_waitDeclarations.erase(
              instance->_waitDeclarations.begin() + absentIndex);
          instance->removeSubWait(decl);
        };
      };
    };
  };
  if (instance->_waitDeclarations.empty()) {
    globals.insertContainer(instance->_waitingClassDeclaration);
    std::vector<MissingSubClassGeneration>::iterator subIterEnd
        = instance->_subGenerations.end();
    std::vector<MissingSubClassGeneration>::iterator subIter
        = instance->_subGenerations.begin();
    /* class_decl */ list* parentDeclList = NULL;
    int parentDeclPosition = 0;
    int subIndex = 0;
    assert(instance->_subGenerations.empty() || (instance
        ->_waitingClassDeclaration->tag_translation_unit_decl == COMPOUND
          && instance->_waitingClassDeclaration->cons_translation_unit_decl
            .Compound.body->is_some));
    while (subIter != subIterEnd && (!subIter->_waitingSubClassDecl
        || subIter->removeWaitWithinClass(instance->key(), parentDeclList,
             (/* class_decl */ list*) &instance->_waitingClassDeclaration
               ->cons_translation_unit_decl.Compound.body->content.container,
             parentDeclPosition, subIter->_parentPosition - subIndex))) {
      solve(*subIter, *instance, globals);
      ++subIter; ++subIndex;
    };
    if (subIter != subIterEnd) {
      // [TODO] use parentDeclList and subIter->_parentPosition
      //   instead of a new list.
      /* class_decl */ list subList = (list) instance->_waitingClassDeclaration
          ->cons_translation_unit_decl.Compound.body->content.container;
      assert(subList);
      while (subList) {
        class_decl classElement = (class_decl) subList->element.container;
        bool isEqual = classElement == subIter->_waitingSubClassDecl;
        if (!isEqual)
          isEqual = classElement->tag_class_decl == CCOMPOUND
            && subIter->_waitingSubClassDecl->tag_class_decl == CCOMPOUND
            && !strcmp(classElement->cons_class_decl.CCompound.name,
                subIter->_waitingSubClassDecl->cons_class_decl.CCompound.name)
            && tkind_equal(
                classElement->cons_class_decl.CCompound.template_kind,
                subIter->_waitingSubClassDecl->cons_class_decl
                  .CCompound.template_kind);
        if (isEqual) {
          addWaitFor(*subIter, subIter->_waitingSubClassDecl, instance, globals,
            classElement != subIter->_waitingSubClassDecl /* shouldBeSubkey */);
          ++subIter; ++subIndex;
          while (subIter != subIterEnd && (!subIter->_waitingSubClassDecl
              || subIter->removeWaitWithinClass(instance->key(), parentDeclList,
                (/* class_decl */ list*) &instance->_waitingClassDeclaration
                  ->cons_translation_unit_decl.Compound.body->content.container,
                parentDeclPosition, subIter->_parentPosition - subIndex))) {
            solve(*subIter, *instance, globals);
            ++subIter; ++subIndex;
          };
          if (subIter == subIterEnd)
            break;
        };
        subList = subList->next;
      };
      assert(subIter == subIterEnd);
    };

    instance->_waitingClassDeclaration = NULL;
    instance->_subGenerations.clear();
    MissingDecl::WaitingDecls::iterator iterEnd
        = instance->_waitingDecls.end();
    for (MissingDecl::WaitingDecls::iterator iter
        = instance->_waitingDecls.begin(); iter != iterEnd; ++iter) {
      if ((*iter)->solve(instance->_key, globals, *this)) {
        KeyInfo* toLocalDelete = *iter;
        ContentTable::iterator localFound = _content.find(toLocalDelete);
        assert(localFound != _content.end() && *localFound == toLocalDelete);
        _content.erase(localFound);
        *iter = new KeyInfo(**iter);
        _content.insert(*iter);
        delete toLocalDelete;
      };
    };
    instance->_waitingDecls.clear();

    ContentTable::iterator found = _content.find(instance);
    assert(found != _content.end());
    _content.erase(found);
    _content.insert(new KeyInfo(*instance));
  }
  else {
    translation_unit_decl definition = instance->_waitingClassDeclaration;
    assert(definition->tag_translation_unit_decl == COMPOUND);
    translation_unit_decl declaration = translation_unit_decl_Compound(
        copy_loc(definition->cons_translation_unit_decl.Compound.loc),
        decl_or_impl_name_dup(definition->cons_translation_unit_decl
            .Compound.name),
        definition->cons_translation_unit_decl.Compound.kind,
        opt_none() /* inherits */, opt_none() /* body */,
        false /* has_virtual */, tkind_dup(
            definition->cons_translation_unit_decl.Compound.template_kind),
        definition->cons_translation_unit_decl.Compound.is_extern_c_context,
        definition->cons_translation_unit_decl.Compound.is_ghost);
    globals.insertContainer(declaration);
    MissingClassGeneration* missingInstance
      = new MissingClassGeneration(*instance);
    enableNotificationFromBeforeReplaceWaiting(
        missingInstance->_waitDeclarations, instance->_waitingDecls,
        missingInstance, false /* mayHaveInstanceClass */);

    MissingDecl::WaitingDecls::iterator iterEnd
        = instance->_waitingDecls.end();
    for (MissingDecl::WaitingDecls::iterator iter
        = instance->_waitingDecls.begin(); iter != iterEnd; ++iter)
      (*iter)->replaceWaitingBy(missingInstance->key(),
          missingInstance->_waitDeclarations);
    instance->_waitingDecls.clear();
    ContentTable::iterator found = _content.find(instance);
    assert(found != _content.end());
    _content.erase(found);
    _content.insert(missingInstance);
    std::set<const clang::Decl*>::const_iterator
      subIterEnd = missingInstance->_subWaitDeclarations.end(),
      subIter = missingInstance->_subWaitDeclarations.begin();
    for (; subIter != subIterEnd; ++subIter) {
      KeyInfo locateKey(*subIter);
      ContentTable::iterator found = _content.lower_bound(&locateKey);
      if (found != _content.end() && (*found)->_key == *subIter) {
        std::vector<KeyInfo*>* waitingDecls = NULL;
        if ((*found)->isInstanceClass())
          waitingDecls = &((InstanceClassGeneration*) *found)->_waitingDecls;
        else {
          assert((*found)->isMissingDecl());
          waitingDecls = &((MissingDecl*) (*found))->waitingDecls();
        };
        MissingDecl::WaitingDecls::const_iterator
          endFindIter = waitingDecls->end(), findIter = waitingDecls->begin();
        bool hasFound = false;
        for (; !hasFound && findIter != endFindIter; ++findIter)
          hasFound = *findIter == missingInstance;
        if (!hasFound)
          waitingDecls->push_back(missingInstance);
      }
      else {
        MissingDecl* newMissing = new MissingDecl(*subIter);
        _content.insert(found, newMissing);
        newMissing->_waitingDecls.push_back(missingInstance);
      };
    }
  };
  delete instance;
}

VisitTable::MissingClassGeneration&
VisitTable::addIncompleteClass(const clang::RecordDecl* decl,
    std::vector<const clang::Decl*>& waitDeclarations,
    translation_unit_decl classDecl) {
  assert(!waitDeclarations.empty());
  KeyInfo locateKey(decl);
  ContentTable::iterator found = _content.lower_bound(&locateKey);
  MissingClassGeneration* result;
  if (found != _content.end() && (*found)->_key == decl) {
    assert((*found)->isMissingDecl());
    MissingDecl* oldMissing = (MissingDecl*) *found;
    result = new MissingClassGeneration(decl, classDecl);
    waitDeclarations.swap(result->_waitDeclarations);
    _content.erase(found);
    _content.insert(result);
    enableNotificationFromBeforeReplaceWaiting(result->_waitDeclarations,
        oldMissing->_waitingDecls, NULL /* originDependencies */,
        false /* mayHaveInstanceClass */);

    MissingDecl::WaitingDecls::iterator iterEnd
        = oldMissing->_waitingDecls.end();
    for (MissingDecl::WaitingDecls::iterator iter
        = oldMissing->_waitingDecls.begin(); iter != iterEnd; ++iter)
      (*iter)->replaceWaitingBy(decl, result->_waitDeclarations);
    delete oldMissing;
  }
  else {
    result = new MissingClassGeneration(decl, classDecl);
    waitDeclarations.swap(result->_waitDeclarations);
    _content.insert(found, result);
  };
  return *result;
}

VisitTable::MissingFunctionGeneration&
VisitTable::addIncompleteFunction(const clang::FunctionDecl* decl,
    std::vector<const clang::Decl*>& waitDeclarations,
    translation_unit_decl functionDecl,
    translation_unit_decl functionBareDecl) {
  assert(!waitDeclarations.empty());
  KeyInfo locateKey(decl);
  ContentTable::iterator found = _content.lower_bound(&locateKey);
  MissingFunctionGeneration* result;
  if (found != _content.end() && (*found)->_key == decl) {
    assert((*found)->isMissingDecl());
    MissingDecl* oldMissing = (MissingDecl*) *found;
    result= new MissingFunctionGeneration(decl, functionDecl, functionBareDecl);
    waitDeclarations.swap(result->_waitDeclarations);
    _content.erase(found);
    _content.insert(result);
    enableNotificationFromBeforeReplaceWaiting(result->_waitDeclarations,
        oldMissing->_waitingDecls, result, true /* mayHaveInstanceClass */);

    MissingDecl::WaitingDecls::iterator iterEnd
        = oldMissing->_waitingDecls.end();
    for (MissingDecl::WaitingDecls::iterator iter
        = oldMissing->_waitingDecls.begin(); iter != iterEnd; ++iter)
      (*iter)->replaceWaitingBy(decl, result->_waitDeclarations);
    delete oldMissing;
  }
  else {
    result= new MissingFunctionGeneration(decl, functionDecl, functionBareDecl);
    waitDeclarations.swap(result->_waitDeclarations);
    std::vector<const clang::Decl*>::iterator
      absentIterEnd = result->_waitDeclarations.end();
    for (std::vector<const clang::Decl*>::iterator
        absentIter = result->_waitDeclarations.begin();
        absentIter != absentIterEnd; ++absentIter) {
      KeyInfo locateKey(*absentIter);
      ContentTable::const_iterator found = _content.find(&locateKey);
      if (found == _content.end()) {
        MissingDecl* newMissing = new MissingDecl(*absentIter);
        _content.insert(newMissing);
        newMissing->_waitingDecls.push_back(result);
      }
      else if ((*found)->isMissingDecl()) { // has locally been found after
        if (((MissingDecl*) *found)->_waitingDecls.empty()
            || ((MissingDecl*) *found)->_waitingDecls.back() != result)
          ((MissingDecl*) *found)->_waitingDecls.push_back(result);
        else {
          int index = absentIter - result->_waitDeclarations.begin();
          result->_waitDeclarations.erase(absentIter);
          absentIter =  result->_waitDeclarations.begin() + index - 1;
          absentIterEnd =  result->_waitDeclarations.end();
        };
      }
      else if ((*found)->isInstanceClass()) {
        if (((InstanceClassGeneration*) *found)->_waitingDecls.empty()
            ||((InstanceClassGeneration*) *found)->_waitingDecls.back()!=result)
          ((InstanceClassGeneration*) *found)->_waitingDecls.push_back(result);
        else {
          int index = absentIter - result->_waitDeclarations.begin();
          result->_waitDeclarations.erase(absentIter);
          absentIter =  result->_waitDeclarations.begin() + index - 1;
          absentIterEnd =  result->_waitDeclarations.end();
        };
      }
      else { // should not occur
        int index = absentIter - result->_waitDeclarations.begin();
        result->_waitDeclarations.erase(absentIter);
        absentIter =  result->_waitDeclarations.begin() + index - 1;
        absentIterEnd =  result->_waitDeclarations.end();
      };
    }
    _content.insert(found, result);
  };
  return *result;
}