Skip to content

Commit 202ab23

Browse files
Merge pull request #8698 from Michael137/lldb/type-completion/cherry-pick-all
[cherry-pick][swift/release/6.0] [lldb][Type Completion] Lazy loading of C++ methods
2 parents b6c291f + 17fce6b commit 202ab23

File tree

21 files changed

+283
-57
lines changed

21 files changed

+283
-57
lines changed

clang/include/clang/AST/ExternalASTSource.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
150150
virtual bool
151151
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
152152

153+
virtual bool FindExternalVisibleMethodsByName(const DeclContext *DC,
154+
DeclarationName Name) {
155+
return false;
156+
}
157+
153158
/// Ensures that the table of all visible declarations inside this
154159
/// context is up to date.
155160
///

clang/lib/AST/ASTImporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1878,7 +1878,7 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
18781878
continue;
18791879
}
18801880

1881-
if (Importer.hasLLDBRedeclCompletion()) {
1881+
if (!Importer.hasLLDBRedeclCompletion()) {
18821882
FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From);
18831883
Decl *ImportedDecl = *ImportedOrErr;
18841884
FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl);

clang/lib/Sema/SemaExprMember.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,13 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
685685
}
686686
}
687687

688+
if (ExternalASTSource *Source =
689+
DC->getParentASTContext().getExternalSource()) {
690+
if (auto LookupName = R.getLookupName()) {
691+
Source->FindExternalVisibleMethodsByName(DC, LookupName);
692+
}
693+
}
694+
688695
// The record definition is complete, now look up the member.
689696
SemaRef.LookupQualifiedName(R, DC, SS);
690697

lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -824,23 +824,17 @@ bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
824824
if (!decl_origin.Valid())
825825
return false;
826826

827-
ImporterDelegateSP delegate_sp(
828-
GetDelegate(&decl->getASTContext(), decl_origin.ctx));
829-
830-
ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
831-
&decl->getASTContext());
832-
833-
if (!TypeSystemClang::UseRedeclCompletion()) {
834-
if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
835-
return false;
836-
837-
if (delegate_sp)
838-
delegate_sp->ImportDefinitionTo(decl, decl_origin.decl);
839-
} else {
827+
if (TypeSystemClang::UseRedeclCompletion()) {
840828
auto *origin_def = llvm::cast<TagDecl>(decl_origin.decl)->getDefinition();
841829
if (!origin_def)
842830
return false;
843831

832+
ImporterDelegateSP delegate_sp(
833+
GetDelegate(&decl->getASTContext(), decl_origin.ctx));
834+
835+
ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
836+
&decl->getASTContext());
837+
844838
// This is expected to pull in a definition for result_decl (if in redecl
845839
// completion mode)
846840
llvm::Expected<Decl *> result = delegate_sp->Import(origin_def);
@@ -859,6 +853,18 @@ bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
859853
if (!decl->isThisDeclarationADefinition() && result_decl != decl)
860854
if (result_decl->getPreviousDecl() == nullptr)
861855
result_decl->setPreviousDecl(decl);
856+
} else {
857+
if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
858+
return false;
859+
860+
ImporterDelegateSP delegate_sp(
861+
GetDelegate(&decl->getASTContext(), decl_origin.ctx));
862+
863+
ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp,
864+
&decl->getASTContext());
865+
866+
if (delegate_sp)
867+
delegate_sp->ImportDefinitionTo(decl, decl_origin.decl);
862868
}
863869

864870
return true;
@@ -880,27 +886,15 @@ bool ClangASTImporter::CompleteObjCInterfaceDecl(
880886
if (!decl_origin.Valid())
881887
return false;
882888

883-
ImporterDelegateSP delegate_sp(
884-
GetDelegate(&interface_decl->getASTContext(), decl_origin.ctx));
885-
886-
if (!TypeSystemClang::UseRedeclCompletion()) {
887-
if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
888-
return false;
889-
890-
if (delegate_sp)
891-
delegate_sp->ImportDefinitionTo(interface_decl, decl_origin.decl);
892-
893-
if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass())
894-
RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0));
895-
} else {
889+
if (TypeSystemClang::UseRedeclCompletion()) {
896890
ObjCInterfaceDecl *origin_decl =
897891
llvm::cast<ObjCInterfaceDecl>(decl_origin.decl);
898892

899893
origin_decl = origin_decl->getDefinition();
900894
if (!origin_decl)
901895
return false;
902896

903-
auto delegate_sp(
897+
ImporterDelegateSP delegate_sp(
904898
GetDelegate(&interface_decl->getASTContext(), decl_origin.ctx));
905899

906900
llvm::Expected<Decl *> result = delegate_sp->Import(origin_decl);
@@ -915,6 +909,18 @@ bool ClangASTImporter::CompleteObjCInterfaceDecl(
915909
return false;
916910
}
917911

912+
if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
913+
return false;
914+
915+
ImporterDelegateSP delegate_sp(
916+
GetDelegate(&interface_decl->getASTContext(), decl_origin.ctx));
917+
918+
if (delegate_sp)
919+
delegate_sp->ImportDefinitionTo(interface_decl, decl_origin.decl);
920+
921+
if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass())
922+
RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0));
923+
918924
return true;
919925
}
920926

@@ -1204,15 +1210,14 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
12041210
DeclContext::lookup_result lr = dc->lookup(*dn_or_err);
12051211
for (clang::Decl *candidate : lr) {
12061212
if (candidate->getKind() == From->getKind()) {
1207-
RegisterImportedDecl(From, candidate);
1208-
12091213
// If we're dealing with redecl chains. We want to find the definition,
12101214
// so skip if the decl is actually just a forwad decl.
12111215
if (TypeSystemClang::UseRedeclCompletion())
12121216
if (auto *tag_decl = llvm::dyn_cast<TagDecl>(candidate);
12131217
!tag_decl || !tag_decl->getDefinition())
12141218
continue;
12151219

1220+
RegisterImportedDecl(From, candidate);
12161221
m_decls_to_ignore.insert(candidate);
12171222
return candidate;
12181223
}

lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "ClangDeclVendor.h"
1212
#include "ClangModulesDeclVendor.h"
1313

14+
#include "NameSearchContext.h"
1415
#include "lldb/Core/Module.h"
1516
#include "lldb/Core/ModuleList.h"
1617
#include "lldb/Symbol/CompilerDeclContext.h"
@@ -21,6 +22,7 @@
2122
#include "lldb/Utility/LLDBLog.h"
2223
#include "lldb/Utility/Log.h"
2324
#include "clang/AST/ASTContext.h"
25+
#include "clang/AST/DeclCXX.h"
2426
#include "clang/Basic/SourceManager.h"
2527

2628
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
@@ -615,6 +617,125 @@ bool ClangASTSource::IgnoreName(const ConstString name,
615617
name_string_ref.startswith("_$");
616618
}
617619

620+
bool ClangASTSource::FindExternalVisibleMethodsByName(
621+
const clang::DeclContext *DC, clang::DeclarationName Name) {
622+
if (!TypeSystemClang::UseRedeclCompletion())
623+
return true;
624+
625+
SmallVector<clang::NamedDecl *> decls;
626+
NameSearchContext context(*m_clang_ast_context, decls, Name, DC);
627+
FindExternalVisibleMethods(context);
628+
629+
return true;
630+
}
631+
632+
void ClangASTSource::FindExternalVisibleMethods(NameSearchContext &context) {
633+
assert(m_ast_context);
634+
635+
const ConstString name(context.m_decl_name.getAsString().c_str());
636+
CompilerDeclContext namespace_decl;
637+
FindExternalVisibleMethods(context, lldb::ModuleSP(), namespace_decl);
638+
}
639+
640+
bool ClangASTSource::CompilerDeclContextsMatch(
641+
CompilerDeclContext candidate_decl_ctx, DeclContext const *context,
642+
TypeSystemClang &ts) {
643+
auto CDC1 = candidate_decl_ctx.GetTypeSystem()->DeclContextGetCompilerContext(
644+
candidate_decl_ctx.GetOpaqueDeclContext());
645+
646+
// Member functions have at least 2 entries (1
647+
// for method name, 1 for parent class)
648+
assert(CDC1.size() > 1);
649+
650+
// drop last entry (which is function name)
651+
CDC1.pop_back();
652+
653+
const auto CDC2 = ts.DeclContextGetCompilerContext(
654+
const_cast<clang::DeclContext *>(context));
655+
656+
// Quick by-name check of the entire context hierarchy.
657+
if (CDC1 == CDC2)
658+
return true;
659+
660+
// Otherwise, check whether the 'candidate_decl_ctx' is a base class of
661+
// 'context'.
662+
auto const *candidate_context =
663+
(static_cast<clang::DeclContext *>(
664+
candidate_decl_ctx.GetOpaqueDeclContext()))
665+
->getParent();
666+
667+
auto const *candidate_cxx_record =
668+
dyn_cast<clang::CXXRecordDecl>(candidate_context);
669+
if (!candidate_cxx_record)
670+
return false;
671+
672+
auto const *cxx_record = dyn_cast<clang::CXXRecordDecl>(context);
673+
if (!cxx_record)
674+
return false;
675+
676+
// cxx_record comes from user expression AST. So we need to get origin
677+
// to compare against candidate_context.
678+
auto orig = GetDeclOrigin(cxx_record);
679+
if (!orig.Valid())
680+
return false;
681+
682+
if (llvm::cast<CXXRecordDecl>(orig.decl)->isDerivedFrom(candidate_cxx_record))
683+
return true;
684+
685+
return false;
686+
}
687+
688+
void ClangASTSource::FindExternalVisibleMethods(
689+
NameSearchContext &context, lldb::ModuleSP module_sp,
690+
CompilerDeclContext &namespace_decl) {
691+
assert(m_ast_context);
692+
693+
SymbolContextList sc_list;
694+
const ConstString name(context.m_decl_name.getAsString().c_str());
695+
if (!m_target)
696+
return;
697+
698+
if (context.m_found_type)
699+
return;
700+
701+
ModuleFunctionSearchOptions function_options;
702+
function_options.include_inlines = false;
703+
function_options.include_symbols = false;
704+
m_target->GetImages().FindFunctions(name, lldb::eFunctionNameTypeMethod,
705+
function_options, sc_list);
706+
707+
auto num_matches = sc_list.GetSize();
708+
if (num_matches == 0)
709+
return;
710+
711+
for (const SymbolContext &sym_ctx : sc_list) {
712+
assert(sym_ctx.function);
713+
CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
714+
if (!decl_ctx)
715+
continue;
716+
717+
assert(decl_ctx.IsClassMethod());
718+
719+
if (!CompilerDeclContextsMatch(decl_ctx, context.m_decl_context,
720+
context.m_clang_ts))
721+
continue;
722+
723+
clang::CXXMethodDecl *src_method = llvm::cast<CXXMethodDecl>(
724+
static_cast<clang::DeclContext *>(decl_ctx.GetOpaqueDeclContext()));
725+
Decl *copied_decl = CopyDecl(src_method);
726+
727+
if (!copied_decl)
728+
continue;
729+
730+
CXXMethodDecl *copied_method_decl = dyn_cast<CXXMethodDecl>(copied_decl);
731+
732+
if (!copied_method_decl)
733+
continue;
734+
735+
context.AddNamedDecl(copied_method_decl);
736+
}
737+
}
738+
618739
void ClangASTSource::FindExternalVisibleDecls(
619740
NameSearchContext &context, lldb::ModuleSP module_sp,
620741
CompilerDeclContext &namespace_decl) {

lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ class ClangASTSource : public ImporterBackedASTSource,
8787
bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
8888
clang::DeclarationName Name) override;
8989

90+
bool FindExternalVisibleMethodsByName(const clang::DeclContext *DC,
91+
clang::DeclarationName Name) override;
92+
9093
/// Enumerate all Decls in a given lexical context.
9194
///
9295
/// \param[in] DC
@@ -197,6 +200,7 @@ class ClangASTSource : public ImporterBackedASTSource,
197200
/// \param[in] context
198201
/// The NameSearchContext to use when filing results.
199202
virtual void FindExternalVisibleDecls(NameSearchContext &context);
203+
virtual void FindExternalVisibleMethods(NameSearchContext &context);
200204

201205
clang::Sema *getSema();
202206

@@ -210,7 +214,7 @@ class ClangASTSource : public ImporterBackedASTSource,
210214
///
211215
/// Clang AST contexts like to own their AST sources, so this is a state-
212216
/// free proxy object.
213-
class ClangASTSourceProxy : public clang::ExternalASTSource {
217+
class ClangASTSourceProxy : public ImporterBackedASTSource {
214218
public:
215219
ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {}
216220

@@ -219,6 +223,12 @@ class ClangASTSource : public ImporterBackedASTSource,
219223
return m_original.FindExternalVisibleDeclsByName(DC, Name);
220224
}
221225

226+
bool
227+
FindExternalVisibleMethodsByName(const clang::DeclContext *DC,
228+
clang::DeclarationName Name) override {
229+
return m_original.FindExternalVisibleMethodsByName(DC, Name);
230+
}
231+
222232
void FindExternalLexicalDecls(
223233
const clang::DeclContext *DC,
224234
llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
@@ -288,6 +298,9 @@ class ClangASTSource : public ImporterBackedASTSource,
288298
void FindExternalVisibleDecls(NameSearchContext &context,
289299
lldb::ModuleSP module,
290300
CompilerDeclContext &namespace_decl);
301+
void FindExternalVisibleMethods(NameSearchContext &context,
302+
lldb::ModuleSP module,
303+
CompilerDeclContext &namespace_decl);
291304

292305
/// Find all Objective-C methods matching a given selector.
293306
///
@@ -364,6 +377,10 @@ class ClangASTSource : public ImporterBackedASTSource,
364377
NameSearchContext &context,
365378
DeclFromUser<const clang::ObjCInterfaceDecl> &origin_iface_decl);
366379

380+
bool CompilerDeclContextsMatch(CompilerDeclContext candidate_decl_ctx,
381+
clang::DeclContext const *context,
382+
TypeSystemClang &ts);
383+
367384
protected:
368385
bool FindObjCMethodDeclsWithOrigin(
369386
NameSearchContext &context,

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,13 @@ void ClangExpressionDeclMap::LookupFunction(
13401340
}
13411341
}
13421342

1343+
void ClangExpressionDeclMap::FindExternalVisibleMethods(
1344+
NameSearchContext &context) {
1345+
assert(m_ast_context);
1346+
1347+
ClangASTSource::FindExternalVisibleMethods(context);
1348+
}
1349+
13431350
void ClangExpressionDeclMap::FindExternalVisibleDecls(
13441351
NameSearchContext &context, lldb::ModuleSP module_sp,
13451352
const CompilerDeclContext &namespace_decl) {

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "ClangASTSource.h"
1919
#include "ClangExpressionVariable.h"
2020

21+
#include "Plugins/ExpressionParser/Clang/NameSearchContext.h"
2122
#include "lldb/Core/Value.h"
2223
#include "lldb/Expression/Materializer.h"
2324
#include "lldb/Symbol/SymbolContext.h"
@@ -266,6 +267,7 @@ class ClangExpressionDeclMap : public ClangASTSource {
266267
/// \param[in] context
267268
/// The NameSearchContext that can construct Decls for this name.
268269
void FindExternalVisibleDecls(NameSearchContext &context) override;
270+
void FindExternalVisibleMethods(NameSearchContext &context) override;
269271

270272
/// Find all entities matching a given name in a given module/namespace,
271273
/// using a NameSearchContext to make Decls for them.

lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ class ClangExternalASTSourceCallbacks : public ImporterBackedASTSource {
3737
bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
3838
clang::DeclarationName Name) override;
3939

40+
bool FindExternalVisibleMethodsByName(const clang::DeclContext *DC,
41+
clang::DeclarationName Name) override {
42+
return false;
43+
}
44+
4045
void CompleteType(clang::TagDecl *tag_decl) override;
4146

4247
void CompleteType(clang::ObjCInterfaceDecl *objc_decl) override;

0 commit comments

Comments
 (0)