@@ -301,7 +301,8 @@ using Entry = llvm::DWARFDebugNames::Entry;
301301// / If any parent does not have an `IDX_parent`, or the Entry data is corrupted,
302302// / nullopt is returned.
303303std::optional<llvm::SmallVector<Entry, 4 >>
304- getParentChain (Entry entry, uint32_t max_parents) {
304+ getParentChain (Entry entry,
305+ uint32_t max_parents = std::numeric_limits<uint32_t >::max()) {
305306 llvm::SmallVector<Entry, 4 > parent_entries;
306307
307308 do {
@@ -374,6 +375,21 @@ void DebugNamesDWARFIndex::GetFullyQualifiedType(
374375 m_fallback.GetFullyQualifiedType (context, callback);
375376}
376377
378+ bool DebugNamesDWARFIndex::SameAsEntryContext (
379+ const CompilerContext &query_context,
380+ const DebugNames::Entry &entry) const {
381+ // TODO: check dwarf tag matches.
382+ // Peek at the AT_name of `entry` and test equality to `name`.
383+ auto maybe_dieoffset = entry.getDIEUnitOffset ();
384+ if (!maybe_dieoffset)
385+ return false ;
386+ DWARFUnit *unit = GetNonSkeletonUnit (entry);
387+ if (!unit)
388+ return false ;
389+ return query_context.name ==
390+ unit->PeekDIEName (unit->GetOffset () + *maybe_dieoffset);
391+ }
392+
377393bool DebugNamesDWARFIndex::SameParentChain (
378394 llvm::ArrayRef<llvm::StringRef> parent_names,
379395 llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
@@ -402,6 +418,45 @@ bool DebugNamesDWARFIndex::SameParentChain(
402418 return true ;
403419}
404420
421+ bool DebugNamesDWARFIndex::SameParentChain (
422+ llvm::ArrayRef<CompilerContext> parent_contexts,
423+ llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
424+ if (parent_entries.size () != parent_contexts.size ())
425+ return false ;
426+
427+ // If the AT_name of any parent fails to match the expected name, we don't
428+ // have a match.
429+ for (auto [parent_context, parent_entry] :
430+ llvm::zip_equal (parent_contexts, parent_entries))
431+ if (!SameAsEntryContext (parent_context, parent_entry))
432+ return false ;
433+ return true ;
434+ }
435+
436+ bool DebugNamesDWARFIndex::WithinParentChain (
437+ llvm::ArrayRef<CompilerContext> query_contexts,
438+ llvm::ArrayRef<DebugNames::Entry> parent_chain) const {
439+ if (query_contexts.size () == parent_chain.size ())
440+ return SameParentChain (query_contexts, parent_chain);
441+
442+ // If parent chain does not have enough entries, we can't possibly have a
443+ // match.
444+ while (!query_contexts.empty () &&
445+ query_contexts.size () <= parent_chain.size ()) {
446+ if (SameAsEntryContext (query_contexts.front (), parent_chain.front ())) {
447+ query_contexts = query_contexts.drop_front ();
448+ parent_chain = parent_chain.drop_front ();
449+ } else {
450+ // Name does not match, try next parent_chain entry if the current entry
451+ // is namespace because the current one can be an inline namespace.
452+ if (parent_chain.front ().tag () != DW_TAG_namespace)
453+ return false ;
454+ parent_chain = parent_chain.drop_front ();
455+ }
456+ }
457+ return query_contexts.empty ();
458+ }
459+
405460void DebugNamesDWARFIndex::GetTypes (
406461 ConstString name, llvm::function_ref<bool (DWARFDIE die)> callback) {
407462 for (const DebugNames::Entry &entry :
@@ -444,6 +499,72 @@ void DebugNamesDWARFIndex::GetNamespaces(
444499 m_fallback.GetNamespaces (name, callback);
445500}
446501
502+ llvm::SmallVector<CompilerContext>
503+ DebugNamesDWARFIndex::GetTypeQueryParentContexts (TypeQuery &query) {
504+ std::vector<lldb_private::CompilerContext> &query_decl_context =
505+ query.GetContextRef ();
506+ llvm::SmallVector<CompilerContext> parent_contexts;
507+ if (!query_decl_context.empty ()) {
508+ // Skip the last entry, it is the type we are looking for.
509+ // Reverse the query decl context to match parent chain.
510+ llvm::ArrayRef<CompilerContext> parent_contexts_ref (
511+ query_decl_context.data (), query_decl_context.size () - 1 );
512+ for (const CompilerContext &ctx : llvm::reverse (parent_contexts_ref)) {
513+ // Skip any context without name because .debug_names might not encode
514+ // them. (e.g. annonymous namespace)
515+ if ((ctx.kind & CompilerContextKind::AnyType) !=
516+ CompilerContextKind::Invalid &&
517+ !ctx.name .IsEmpty ())
518+ parent_contexts.push_back (ctx);
519+ }
520+ }
521+ return parent_contexts;
522+ }
523+
524+ void DebugNamesDWARFIndex::GetTypesWithQuery (
525+ TypeQuery &query, llvm::function_ref<bool (DWARFDIE die)> callback) {
526+ ConstString name = query.GetTypeBasename ();
527+ std::vector<lldb_private::CompilerContext> query_context =
528+ query.GetContextRef ();
529+ if (query_context.size () <= 1 )
530+ return GetTypes (name, callback);
531+
532+ llvm::SmallVector<CompilerContext> parent_contexts =
533+ GetTypeQueryParentContexts (query);
534+ // For each entry, grab its parent chain and check if we have a match.
535+ for (const DebugNames::Entry &entry : m_debug_names_up->equal_range (name)) {
536+ if (!isType (entry.tag ()))
537+ continue ;
538+
539+ // If we get a NULL foreign_tu back, the entry doesn't match the type unit
540+ // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
541+ // didn't match.
542+ std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit (entry);
543+ if (foreign_tu && foreign_tu.value () == nullptr )
544+ continue ;
545+
546+ std::optional<llvm::SmallVector<Entry, 4 >> parent_chain =
547+ getParentChain (entry);
548+ if (!parent_chain) {
549+ // Fallback: use the base class implementation.
550+ if (!ProcessEntry (entry, [&](DWARFDIE die) {
551+ return ProcessTypeDIEMatchQuery (query, die, callback);
552+ }))
553+ return ;
554+ continue ;
555+ }
556+
557+ if (WithinParentChain (parent_contexts, *parent_chain) &&
558+ !ProcessEntry (entry, [&](DWARFDIE die) {
559+ // After .debug_names filtering still sending to base class for
560+ // further filtering before calling the callback.
561+ return ProcessTypeDIEMatchQuery (query, die, callback);
562+ }))
563+ return ;
564+ }
565+ m_fallback.GetTypesWithQuery (query, callback);
566+ }
567+
447568void DebugNamesDWARFIndex::GetFunctions (
448569 const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
449570 const CompilerDeclContext &parent_decl_ctx,
0 commit comments