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;
}