Cxx::XRefTarget retarget()

in glean/lang/clang/ast.cpp [87:127]


  Cxx::XRefTarget retarget(
      const clang::Decl * FOLLY_NULLABLE base,
      Cxx::XRefTarget target) {
    if (base) {
      if (const auto decl =
            clang::dyn_cast_or_null<clang::NamedDecl>(
              base->getCanonicalDecl())) {
        const auto declContext =
          getCanonicalDeclContext(decl->getDeclContext());
        if (declContext != currentContext) {
          const clang::DeclContext *parentContext = nullptr;
          // For non-scoped enumerators, we need to take into account that
          // using the enclosing namespace of the enum type also brings the
          // enumerators into scope:
          //
          // namespace N1 { enum E { A } };
          // namespace N2 { using namespace N1; /* A is in scope */ }
          // namespace N3 { using N1::E; /* A isn't in scope */ }
          //
          // So we have to look for the DeclContext of the enum (but not for
          // the enum itself).
          if (auto enm =
                clang::dyn_cast_or_null<clang::EnumDecl>(declContext)) {
            if (!enm->isScoped()) {
              parentContext = getCanonicalDeclContext(
                enm->getCanonicalDecl()->getDeclContext());
            }
          }
          if (parentContext != currentContext) {
            LookupState state{decl, declContext, parentContext, {}, {}};
            lookup(currentContext, state);
            for (const auto& via : state.via) {
              target = Cxx::XRefTarget::indirect(
                db.fact<Cxx::XRefIndirectTarget>(via, target));
            }
          }
        }
      }
    }
    return target;
  }