1 //===-- ASTUtils.h ----------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef liblldb_ASTUtils_h_
10 #define liblldb_ASTUtils_h_
12 #include "clang/Sema/Lookup.h"
13 #include "clang/Sema/MultiplexExternalSemaSource.h"
14 #include "clang/Sema/Sema.h"
15 #include "clang/Sema/SemaConsumer.h"
17 namespace lldb_private {
19 /// Wraps an ExternalASTSource into an ExternalSemaSource. Doesn't take
20 /// ownership of the provided source.
21 class ExternalASTSourceWrapper : public clang::ExternalSemaSource {
22 ExternalASTSource *m_Source;
25 ExternalASTSourceWrapper(ExternalASTSource *Source) : m_Source(Source) {
26 assert(m_Source && "Can't wrap nullptr ExternalASTSource");
29 ~ExternalASTSourceWrapper() override;
31 clang::Decl *GetExternalDecl(uint32_t ID) override {
32 return m_Source->GetExternalDecl(ID);
35 clang::Selector GetExternalSelector(uint32_t ID) override {
36 return m_Source->GetExternalSelector(ID);
39 uint32_t GetNumExternalSelectors() override {
40 return m_Source->GetNumExternalSelectors();
43 clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {
44 return m_Source->GetExternalDeclStmt(Offset);
47 clang::CXXCtorInitializer **
48 GetExternalCXXCtorInitializers(uint64_t Offset) override {
49 return m_Source->GetExternalCXXCtorInitializers(Offset);
52 clang::CXXBaseSpecifier *
53 GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
54 return m_Source->GetExternalCXXBaseSpecifiers(Offset);
57 void updateOutOfDateIdentifier(clang::IdentifierInfo &II) override {
58 m_Source->updateOutOfDateIdentifier(II);
61 bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
62 clang::DeclarationName Name) override {
63 return m_Source->FindExternalVisibleDeclsByName(DC, Name);
66 void completeVisibleDeclsMap(const clang::DeclContext *DC) override {
67 m_Source->completeVisibleDeclsMap(DC);
70 clang::Module *getModule(unsigned ID) override {
71 return m_Source->getModule(ID);
74 llvm::Optional<ASTSourceDescriptor>
75 getSourceDescriptor(unsigned ID) override {
76 return m_Source->getSourceDescriptor(ID);
79 ExtKind hasExternalDefinitions(const clang::Decl *D) override {
80 return m_Source->hasExternalDefinitions(D);
83 void FindExternalLexicalDecls(
84 const clang::DeclContext *DC,
85 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
86 llvm::SmallVectorImpl<clang::Decl *> &Result) override {
87 m_Source->FindExternalLexicalDecls(DC, IsKindWeWant, Result);
91 FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,
92 llvm::SmallVectorImpl<clang::Decl *> &Decls) override {
93 m_Source->FindFileRegionDecls(File, Offset, Length, Decls);
96 void CompleteRedeclChain(const clang::Decl *D) override {
97 m_Source->CompleteRedeclChain(D);
100 void CompleteType(clang::TagDecl *Tag) override {
101 m_Source->CompleteType(Tag);
104 void CompleteType(clang::ObjCInterfaceDecl *Class) override {
105 m_Source->CompleteType(Class);
108 void ReadComments() override { m_Source->ReadComments(); }
110 void StartedDeserializing() override { m_Source->StartedDeserializing(); }
112 void FinishedDeserializing() override { m_Source->FinishedDeserializing(); }
114 void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
115 m_Source->StartTranslationUnit(Consumer);
118 void PrintStats() override;
120 bool layoutRecordType(
121 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
122 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
123 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
125 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
126 &VirtualBaseOffsets) override {
127 return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets,
128 BaseOffsets, VirtualBaseOffsets);
132 /// Wraps an ASTConsumer into an SemaConsumer. Doesn't take ownership of the
133 /// provided consumer. If the provided ASTConsumer is also a SemaConsumer,
134 /// the wrapper will also forward SemaConsumer functions.
135 class ASTConsumerForwarder : public clang::SemaConsumer {
136 clang::ASTConsumer *m_c;
137 clang::SemaConsumer *m_sc;
140 ASTConsumerForwarder(clang::ASTConsumer *c) : m_c(c) {
141 m_sc = llvm::dyn_cast<clang::SemaConsumer>(m_c);
144 ~ASTConsumerForwarder() override;
146 void Initialize(clang::ASTContext &Context) override {
147 m_c->Initialize(Context);
150 bool HandleTopLevelDecl(clang::DeclGroupRef D) override {
151 return m_c->HandleTopLevelDecl(D);
154 void HandleInlineFunctionDefinition(clang::FunctionDecl *D) override {
155 m_c->HandleInlineFunctionDefinition(D);
158 void HandleInterestingDecl(clang::DeclGroupRef D) override {
159 m_c->HandleInterestingDecl(D);
162 void HandleTranslationUnit(clang::ASTContext &Ctx) override {
163 m_c->HandleTranslationUnit(Ctx);
166 void HandleTagDeclDefinition(clang::TagDecl *D) override {
167 m_c->HandleTagDeclDefinition(D);
170 void HandleTagDeclRequiredDefinition(const clang::TagDecl *D) override {
171 m_c->HandleTagDeclRequiredDefinition(D);
174 void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl *D) override {
175 m_c->HandleCXXImplicitFunctionInstantiation(D);
178 void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D) override {
179 m_c->HandleTopLevelDeclInObjCContainer(D);
182 void HandleImplicitImportDecl(clang::ImportDecl *D) override {
183 m_c->HandleImplicitImportDecl(D);
186 void CompleteTentativeDefinition(clang::VarDecl *D) override {
187 m_c->CompleteTentativeDefinition(D);
190 void AssignInheritanceModel(clang::CXXRecordDecl *RD) override {
191 m_c->AssignInheritanceModel(RD);
194 void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *D) override {
195 m_c->HandleCXXStaticMemberVarInstantiation(D);
198 void HandleVTable(clang::CXXRecordDecl *RD) override {
199 m_c->HandleVTable(RD);
202 clang::ASTMutationListener *GetASTMutationListener() override {
203 return m_c->GetASTMutationListener();
206 clang::ASTDeserializationListener *GetASTDeserializationListener() override {
207 return m_c->GetASTDeserializationListener();
210 void PrintStats() override;
212 void InitializeSema(clang::Sema &S) override {
214 m_sc->InitializeSema(S);
217 /// Inform the semantic consumer that Sema is no longer available.
218 void ForgetSema() override {
223 bool shouldSkipFunctionBody(clang::Decl *D) override {
224 return m_c->shouldSkipFunctionBody(D);
228 /// A ExternalSemaSource multiplexer that prioritizes its sources.
230 /// This ExternalSemaSource will forward all requests to its attached sources.
231 /// However, unlike a normal multiplexer it will not forward a request to all
232 /// sources, but instead give priority to certain sources. If a source with a
233 /// higher priority can fulfill a request, all sources with a lower priority
234 /// will not receive the request.
236 /// This class is mostly use to multiplex between sources of different
237 /// 'quality', e.g. a C++ modules and debug information. The C++ module will
238 /// provide more accurate replies to the requests, but might not be able to
239 /// answer all requests. The debug information will be used as a fallback then
240 /// to provide information that is not in the C++ module.
241 class SemaSourceWithPriorities : public clang::ExternalSemaSource {
244 /// The sources ordered in decreasing priority.
245 llvm::SmallVector<clang::ExternalSemaSource *, 2> Sources;
248 /// Construct a SemaSourceWithPriorities with a 'high quality' source that
249 /// has the higher priority and a 'low quality' source that will be used
251 SemaSourceWithPriorities(clang::ExternalSemaSource &high_quality_source,
252 clang::ExternalSemaSource &low_quality_source) {
253 Sources.push_back(&high_quality_source);
254 Sources.push_back(&low_quality_source);
257 ~SemaSourceWithPriorities() override;
259 void addSource(clang::ExternalSemaSource &source) {
260 Sources.push_back(&source);
263 //===--------------------------------------------------------------------===//
264 // ExternalASTSource.
265 //===--------------------------------------------------------------------===//
267 clang::Decl *GetExternalDecl(uint32_t ID) override {
268 for (size_t i = 0; i < Sources.size(); ++i)
269 if (clang::Decl *Result = Sources[i]->GetExternalDecl(ID))
274 void CompleteRedeclChain(const clang::Decl *D) override {
275 for (size_t i = 0; i < Sources.size(); ++i)
276 Sources[i]->CompleteRedeclChain(D);
279 clang::Selector GetExternalSelector(uint32_t ID) override {
281 for (size_t i = 0; i < Sources.size(); ++i) {
282 Sel = Sources[i]->GetExternalSelector(ID);
289 uint32_t GetNumExternalSelectors() override {
290 for (size_t i = 0; i < Sources.size(); ++i)
291 if (uint32_t total = Sources[i]->GetNumExternalSelectors())
296 clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {
297 for (size_t i = 0; i < Sources.size(); ++i)
298 if (clang::Stmt *Result = Sources[i]->GetExternalDeclStmt(Offset))
303 clang::CXXBaseSpecifier *
304 GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
305 for (size_t i = 0; i < Sources.size(); ++i)
306 if (clang::CXXBaseSpecifier *R =
307 Sources[i]->GetExternalCXXBaseSpecifiers(Offset))
312 clang::CXXCtorInitializer **
313 GetExternalCXXCtorInitializers(uint64_t Offset) override {
314 for (auto *S : Sources)
315 if (auto *R = S->GetExternalCXXCtorInitializers(Offset))
320 ExtKind hasExternalDefinitions(const clang::Decl *D) override {
321 for (const auto &S : Sources)
322 if (auto EK = S->hasExternalDefinitions(D))
323 if (EK != EK_ReplyHazy)
328 bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
329 clang::DeclarationName Name) override {
330 for (size_t i = 0; i < Sources.size(); ++i)
331 if (Sources[i]->FindExternalVisibleDeclsByName(DC, Name))
336 void completeVisibleDeclsMap(const clang::DeclContext *DC) override {
337 // FIXME: Only one source should be able to complete the decls map.
338 for (size_t i = 0; i < Sources.size(); ++i)
339 Sources[i]->completeVisibleDeclsMap(DC);
342 void FindExternalLexicalDecls(
343 const clang::DeclContext *DC,
344 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
345 llvm::SmallVectorImpl<clang::Decl *> &Result) override {
346 for (size_t i = 0; i < Sources.size(); ++i) {
347 Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result);
354 FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,
355 llvm::SmallVectorImpl<clang::Decl *> &Decls) override {
356 for (size_t i = 0; i < Sources.size(); ++i)
357 Sources[i]->FindFileRegionDecls(File, Offset, Length, Decls);
360 void CompleteType(clang::TagDecl *Tag) override {
361 while (!Tag->isCompleteDefinition())
362 for (size_t i = 0; i < Sources.size(); ++i) {
363 // FIXME: We are technically supposed to loop here too until
364 // Tag->isCompleteDefinition() is true, but if our low quality source
365 // is failing to complete the tag this code will deadlock.
366 Sources[i]->CompleteType(Tag);
367 if (Tag->isCompleteDefinition())
372 void CompleteType(clang::ObjCInterfaceDecl *Class) override {
373 for (size_t i = 0; i < Sources.size(); ++i)
374 Sources[i]->CompleteType(Class);
377 void ReadComments() override {
378 for (size_t i = 0; i < Sources.size(); ++i)
379 Sources[i]->ReadComments();
382 void StartedDeserializing() override {
383 for (size_t i = 0; i < Sources.size(); ++i)
384 Sources[i]->StartedDeserializing();
387 void FinishedDeserializing() override {
388 for (size_t i = 0; i < Sources.size(); ++i)
389 Sources[i]->FinishedDeserializing();
392 void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
393 for (size_t i = 0; i < Sources.size(); ++i)
394 Sources[i]->StartTranslationUnit(Consumer);
397 void PrintStats() override;
399 clang::Module *getModule(unsigned ID) override {
400 for (size_t i = 0; i < Sources.size(); ++i)
401 if (auto M = Sources[i]->getModule(ID))
406 bool DeclIsFromPCHWithObjectFile(const clang::Decl *D) override {
407 for (auto *S : Sources)
408 if (S->DeclIsFromPCHWithObjectFile(D))
413 bool layoutRecordType(
414 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
415 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
416 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
418 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
419 &VirtualBaseOffsets) override {
420 for (size_t i = 0; i < Sources.size(); ++i)
421 if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets,
422 BaseOffsets, VirtualBaseOffsets))
427 void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override {
428 for (auto &Source : Sources)
429 Source->getMemoryBufferSizes(sizes);
432 //===--------------------------------------------------------------------===//
433 // ExternalSemaSource.
434 //===--------------------------------------------------------------------===//
436 void InitializeSema(clang::Sema &S) override {
437 for (auto &Source : Sources)
438 Source->InitializeSema(S);
441 void ForgetSema() override {
442 for (auto &Source : Sources)
443 Source->ForgetSema();
446 void ReadMethodPool(clang::Selector Sel) override {
447 for (auto &Source : Sources)
448 Source->ReadMethodPool(Sel);
451 void updateOutOfDateSelector(clang::Selector Sel) override {
452 for (auto &Source : Sources)
453 Source->updateOutOfDateSelector(Sel);
456 void ReadKnownNamespaces(
457 llvm::SmallVectorImpl<clang::NamespaceDecl *> &Namespaces) override {
458 for (auto &Source : Sources)
459 Source->ReadKnownNamespaces(Namespaces);
462 void ReadUndefinedButUsed(
463 llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined)
465 for (auto &Source : Sources)
466 Source->ReadUndefinedButUsed(Undefined);
469 void ReadMismatchingDeleteExpressions(
470 llvm::MapVector<clang::FieldDecl *,
471 llvm::SmallVector<std::pair<clang::SourceLocation, bool>,
472 4>> &Exprs) override {
473 for (auto &Source : Sources)
474 Source->ReadMismatchingDeleteExpressions(Exprs);
477 bool LookupUnqualified(clang::LookupResult &R, clang::Scope *S) override {
478 for (auto &Source : Sources) {
479 Source->LookupUnqualified(R, S);
487 void ReadTentativeDefinitions(
488 llvm::SmallVectorImpl<clang::VarDecl *> &Defs) override {
489 for (auto &Source : Sources)
490 Source->ReadTentativeDefinitions(Defs);
493 void ReadUnusedFileScopedDecls(
494 llvm::SmallVectorImpl<const clang::DeclaratorDecl *> &Decls) override {
495 for (auto &Source : Sources)
496 Source->ReadUnusedFileScopedDecls(Decls);
499 void ReadDelegatingConstructors(
500 llvm::SmallVectorImpl<clang::CXXConstructorDecl *> &Decls) override {
501 for (auto &Source : Sources)
502 Source->ReadDelegatingConstructors(Decls);
505 void ReadExtVectorDecls(
506 llvm::SmallVectorImpl<clang::TypedefNameDecl *> &Decls) override {
507 for (auto &Source : Sources)
508 Source->ReadExtVectorDecls(Decls);
511 void ReadUnusedLocalTypedefNameCandidates(
512 llvm::SmallSetVector<const clang::TypedefNameDecl *, 4> &Decls) override {
513 for (auto &Source : Sources)
514 Source->ReadUnusedLocalTypedefNameCandidates(Decls);
517 void ReadReferencedSelectors(
518 llvm::SmallVectorImpl<std::pair<clang::Selector, clang::SourceLocation>>
520 for (auto &Source : Sources)
521 Source->ReadReferencedSelectors(Sels);
524 void ReadWeakUndeclaredIdentifiers(
525 llvm::SmallVectorImpl<std::pair<clang::IdentifierInfo *, clang::WeakInfo>>
527 for (auto &Source : Sources)
528 Source->ReadWeakUndeclaredIdentifiers(WI);
531 void ReadUsedVTables(
532 llvm::SmallVectorImpl<clang::ExternalVTableUse> &VTables) override {
533 for (auto &Source : Sources)
534 Source->ReadUsedVTables(VTables);
537 void ReadPendingInstantiations(
538 llvm::SmallVectorImpl<
539 std::pair<clang::ValueDecl *, clang::SourceLocation>> &Pending)
541 for (auto &Source : Sources)
542 Source->ReadPendingInstantiations(Pending);
545 void ReadLateParsedTemplates(
546 llvm::MapVector<const clang::FunctionDecl *,
547 std::unique_ptr<clang::LateParsedTemplate>> &LPTMap)
549 for (auto &Source : Sources)
550 Source->ReadLateParsedTemplates(LPTMap);
553 clang::TypoCorrection
554 CorrectTypo(const clang::DeclarationNameInfo &Typo, int LookupKind,
555 clang::Scope *S, clang::CXXScopeSpec *SS,
556 clang::CorrectionCandidateCallback &CCC,
557 clang::DeclContext *MemberContext, bool EnteringContext,
558 const clang::ObjCObjectPointerType *OPT) override {
559 for (auto &Source : Sources) {
560 if (clang::TypoCorrection C =
561 Source->CorrectTypo(Typo, LookupKind, S, SS, CCC,
562 MemberContext, EnteringContext, OPT))
565 return clang::TypoCorrection();
568 bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc,
569 clang::QualType T) override {
570 for (auto &Source : Sources) {
571 if (Source->MaybeDiagnoseMissingCompleteType(Loc, T))
578 } // namespace lldb_private
579 #endif // liblldb_ASTUtils_h_