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 LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H
10 #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H
12 #include "clang/Basic/Module.h"
13 #include "clang/Sema/Lookup.h"
14 #include "clang/Sema/MultiplexExternalSemaSource.h"
15 #include "clang/Sema/Sema.h"
16 #include "clang/Sema/SemaConsumer.h"
19 namespace lldb_private
{
21 /// Wraps an ExternalASTSource into an ExternalSemaSource. Doesn't take
22 /// ownership of the provided source.
23 class ExternalASTSourceWrapper
: public clang::ExternalSemaSource
{
24 ExternalASTSource
*m_Source
;
27 ExternalASTSourceWrapper(ExternalASTSource
*Source
) : m_Source(Source
) {
28 assert(m_Source
&& "Can't wrap nullptr ExternalASTSource");
31 ~ExternalASTSourceWrapper() override
;
33 clang::Decl
*GetExternalDecl(uint32_t ID
) override
{
34 return m_Source
->GetExternalDecl(ID
);
37 clang::Selector
GetExternalSelector(uint32_t ID
) override
{
38 return m_Source
->GetExternalSelector(ID
);
41 uint32_t GetNumExternalSelectors() override
{
42 return m_Source
->GetNumExternalSelectors();
45 clang::Stmt
*GetExternalDeclStmt(uint64_t Offset
) override
{
46 return m_Source
->GetExternalDeclStmt(Offset
);
49 clang::CXXCtorInitializer
**
50 GetExternalCXXCtorInitializers(uint64_t Offset
) override
{
51 return m_Source
->GetExternalCXXCtorInitializers(Offset
);
54 clang::CXXBaseSpecifier
*
55 GetExternalCXXBaseSpecifiers(uint64_t Offset
) override
{
56 return m_Source
->GetExternalCXXBaseSpecifiers(Offset
);
59 void updateOutOfDateIdentifier(clang::IdentifierInfo
&II
) override
{
60 m_Source
->updateOutOfDateIdentifier(II
);
63 bool FindExternalVisibleDeclsByName(const clang::DeclContext
*DC
,
64 clang::DeclarationName Name
) override
{
65 return m_Source
->FindExternalVisibleDeclsByName(DC
, Name
);
68 void completeVisibleDeclsMap(const clang::DeclContext
*DC
) override
{
69 m_Source
->completeVisibleDeclsMap(DC
);
72 clang::Module
*getModule(unsigned ID
) override
{
73 return m_Source
->getModule(ID
);
76 std::optional
<clang::ASTSourceDescriptor
>
77 getSourceDescriptor(unsigned ID
) override
{
78 return m_Source
->getSourceDescriptor(ID
);
81 ExtKind
hasExternalDefinitions(const clang::Decl
*D
) override
{
82 return m_Source
->hasExternalDefinitions(D
);
85 void FindExternalLexicalDecls(
86 const clang::DeclContext
*DC
,
87 llvm::function_ref
<bool(clang::Decl::Kind
)> IsKindWeWant
,
88 llvm::SmallVectorImpl
<clang::Decl
*> &Result
) override
{
89 m_Source
->FindExternalLexicalDecls(DC
, IsKindWeWant
, Result
);
93 FindFileRegionDecls(clang::FileID File
, unsigned Offset
, unsigned Length
,
94 llvm::SmallVectorImpl
<clang::Decl
*> &Decls
) override
{
95 m_Source
->FindFileRegionDecls(File
, Offset
, Length
, Decls
);
98 void CompleteRedeclChain(const clang::Decl
*D
) override
{
99 m_Source
->CompleteRedeclChain(D
);
102 void CompleteType(clang::TagDecl
*Tag
) override
{
103 m_Source
->CompleteType(Tag
);
106 void CompleteType(clang::ObjCInterfaceDecl
*Class
) override
{
107 m_Source
->CompleteType(Class
);
110 void ReadComments() override
{ m_Source
->ReadComments(); }
112 void StartedDeserializing() override
{ m_Source
->StartedDeserializing(); }
114 void FinishedDeserializing() override
{ m_Source
->FinishedDeserializing(); }
116 void StartTranslationUnit(clang::ASTConsumer
*Consumer
) override
{
117 m_Source
->StartTranslationUnit(Consumer
);
120 void PrintStats() override
;
122 bool layoutRecordType(
123 const clang::RecordDecl
*Record
, uint64_t &Size
, uint64_t &Alignment
,
124 llvm::DenseMap
<const clang::FieldDecl
*, uint64_t> &FieldOffsets
,
125 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
127 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
128 &VirtualBaseOffsets
) override
{
129 return m_Source
->layoutRecordType(Record
, Size
, Alignment
, FieldOffsets
,
130 BaseOffsets
, VirtualBaseOffsets
);
134 /// Wraps an ASTConsumer into an SemaConsumer. Doesn't take ownership of the
135 /// provided consumer. If the provided ASTConsumer is also a SemaConsumer,
136 /// the wrapper will also forward SemaConsumer functions.
137 class ASTConsumerForwarder
: public clang::SemaConsumer
{
138 clang::ASTConsumer
*m_c
;
139 clang::SemaConsumer
*m_sc
;
142 ASTConsumerForwarder(clang::ASTConsumer
*c
) : m_c(c
) {
143 m_sc
= llvm::dyn_cast
<clang::SemaConsumer
>(m_c
);
146 ~ASTConsumerForwarder() override
;
148 void Initialize(clang::ASTContext
&Context
) override
{
149 m_c
->Initialize(Context
);
152 bool HandleTopLevelDecl(clang::DeclGroupRef D
) override
{
153 return m_c
->HandleTopLevelDecl(D
);
156 void HandleInlineFunctionDefinition(clang::FunctionDecl
*D
) override
{
157 m_c
->HandleInlineFunctionDefinition(D
);
160 void HandleInterestingDecl(clang::DeclGroupRef D
) override
{
161 m_c
->HandleInterestingDecl(D
);
164 void HandleTranslationUnit(clang::ASTContext
&Ctx
) override
{
165 m_c
->HandleTranslationUnit(Ctx
);
168 void HandleTagDeclDefinition(clang::TagDecl
*D
) override
{
169 m_c
->HandleTagDeclDefinition(D
);
172 void HandleTagDeclRequiredDefinition(const clang::TagDecl
*D
) override
{
173 m_c
->HandleTagDeclRequiredDefinition(D
);
176 void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl
*D
) override
{
177 m_c
->HandleCXXImplicitFunctionInstantiation(D
);
180 void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D
) override
{
181 m_c
->HandleTopLevelDeclInObjCContainer(D
);
184 void HandleImplicitImportDecl(clang::ImportDecl
*D
) override
{
185 m_c
->HandleImplicitImportDecl(D
);
188 void CompleteTentativeDefinition(clang::VarDecl
*D
) override
{
189 m_c
->CompleteTentativeDefinition(D
);
192 void AssignInheritanceModel(clang::CXXRecordDecl
*RD
) override
{
193 m_c
->AssignInheritanceModel(RD
);
196 void HandleCXXStaticMemberVarInstantiation(clang::VarDecl
*D
) override
{
197 m_c
->HandleCXXStaticMemberVarInstantiation(D
);
200 void HandleVTable(clang::CXXRecordDecl
*RD
) override
{
201 m_c
->HandleVTable(RD
);
204 clang::ASTMutationListener
*GetASTMutationListener() override
{
205 return m_c
->GetASTMutationListener();
208 clang::ASTDeserializationListener
*GetASTDeserializationListener() override
{
209 return m_c
->GetASTDeserializationListener();
212 void PrintStats() override
;
214 void InitializeSema(clang::Sema
&S
) override
{
216 m_sc
->InitializeSema(S
);
219 /// Inform the semantic consumer that Sema is no longer available.
220 void ForgetSema() override
{
225 bool shouldSkipFunctionBody(clang::Decl
*D
) override
{
226 return m_c
->shouldSkipFunctionBody(D
);
230 /// A ExternalSemaSource multiplexer that prioritizes its sources.
232 /// This ExternalSemaSource will forward all requests to its attached sources.
233 /// However, unlike a normal multiplexer it will not forward a request to all
234 /// sources, but instead give priority to certain sources. If a source with a
235 /// higher priority can fulfill a request, all sources with a lower priority
236 /// will not receive the request.
238 /// This class is mostly use to multiplex between sources of different
239 /// 'quality', e.g. a C++ modules and debug information. The C++ module will
240 /// provide more accurate replies to the requests, but might not be able to
241 /// answer all requests. The debug information will be used as a fallback then
242 /// to provide information that is not in the C++ module.
243 class SemaSourceWithPriorities
: public clang::ExternalSemaSource
{
246 /// The sources ordered in decreasing priority.
247 llvm::SmallVector
<clang::ExternalSemaSource
*, 2> Sources
;
250 /// Construct a SemaSourceWithPriorities with a 'high quality' source that
251 /// has the higher priority and a 'low quality' source that will be used
253 SemaSourceWithPriorities(clang::ExternalSemaSource
&high_quality_source
,
254 clang::ExternalSemaSource
&low_quality_source
) {
255 Sources
.push_back(&high_quality_source
);
256 Sources
.push_back(&low_quality_source
);
259 ~SemaSourceWithPriorities() override
;
261 void addSource(clang::ExternalSemaSource
&source
) {
262 Sources
.push_back(&source
);
265 //===--------------------------------------------------------------------===//
266 // ExternalASTSource.
267 //===--------------------------------------------------------------------===//
269 clang::Decl
*GetExternalDecl(uint32_t ID
) override
{
270 for (size_t i
= 0; i
< Sources
.size(); ++i
)
271 if (clang::Decl
*Result
= Sources
[i
]->GetExternalDecl(ID
))
276 void CompleteRedeclChain(const clang::Decl
*D
) override
{
277 for (size_t i
= 0; i
< Sources
.size(); ++i
)
278 Sources
[i
]->CompleteRedeclChain(D
);
281 clang::Selector
GetExternalSelector(uint32_t ID
) override
{
283 for (size_t i
= 0; i
< Sources
.size(); ++i
) {
284 Sel
= Sources
[i
]->GetExternalSelector(ID
);
291 uint32_t GetNumExternalSelectors() override
{
292 for (size_t i
= 0; i
< Sources
.size(); ++i
)
293 if (uint32_t total
= Sources
[i
]->GetNumExternalSelectors())
298 clang::Stmt
*GetExternalDeclStmt(uint64_t Offset
) override
{
299 for (size_t i
= 0; i
< Sources
.size(); ++i
)
300 if (clang::Stmt
*Result
= Sources
[i
]->GetExternalDeclStmt(Offset
))
305 clang::CXXBaseSpecifier
*
306 GetExternalCXXBaseSpecifiers(uint64_t Offset
) override
{
307 for (size_t i
= 0; i
< Sources
.size(); ++i
)
308 if (clang::CXXBaseSpecifier
*R
=
309 Sources
[i
]->GetExternalCXXBaseSpecifiers(Offset
))
314 clang::CXXCtorInitializer
**
315 GetExternalCXXCtorInitializers(uint64_t Offset
) override
{
316 for (auto *S
: Sources
)
317 if (auto *R
= S
->GetExternalCXXCtorInitializers(Offset
))
322 ExtKind
hasExternalDefinitions(const clang::Decl
*D
) override
{
323 for (const auto &S
: Sources
)
324 if (auto EK
= S
->hasExternalDefinitions(D
))
325 if (EK
!= EK_ReplyHazy
)
330 bool FindExternalVisibleDeclsByName(const clang::DeclContext
*DC
,
331 clang::DeclarationName Name
) override
{
332 for (size_t i
= 0; i
< Sources
.size(); ++i
)
333 if (Sources
[i
]->FindExternalVisibleDeclsByName(DC
, Name
))
338 void completeVisibleDeclsMap(const clang::DeclContext
*DC
) override
{
339 // FIXME: Only one source should be able to complete the decls map.
340 for (size_t i
= 0; i
< Sources
.size(); ++i
)
341 Sources
[i
]->completeVisibleDeclsMap(DC
);
344 void FindExternalLexicalDecls(
345 const clang::DeclContext
*DC
,
346 llvm::function_ref
<bool(clang::Decl::Kind
)> IsKindWeWant
,
347 llvm::SmallVectorImpl
<clang::Decl
*> &Result
) override
{
348 for (size_t i
= 0; i
< Sources
.size(); ++i
) {
349 Sources
[i
]->FindExternalLexicalDecls(DC
, IsKindWeWant
, Result
);
356 FindFileRegionDecls(clang::FileID File
, unsigned Offset
, unsigned Length
,
357 llvm::SmallVectorImpl
<clang::Decl
*> &Decls
) override
{
358 for (size_t i
= 0; i
< Sources
.size(); ++i
)
359 Sources
[i
]->FindFileRegionDecls(File
, Offset
, Length
, Decls
);
362 void CompleteType(clang::TagDecl
*Tag
) override
{
363 for (clang::ExternalSemaSource
*S
: Sources
) {
364 S
->CompleteType(Tag
);
365 // Stop after the first source completed the type.
366 if (Tag
->isCompleteDefinition())
371 void CompleteType(clang::ObjCInterfaceDecl
*Class
) override
{
372 for (size_t i
= 0; i
< Sources
.size(); ++i
)
373 Sources
[i
]->CompleteType(Class
);
376 void ReadComments() override
{
377 for (size_t i
= 0; i
< Sources
.size(); ++i
)
378 Sources
[i
]->ReadComments();
381 void StartedDeserializing() override
{
382 for (size_t i
= 0; i
< Sources
.size(); ++i
)
383 Sources
[i
]->StartedDeserializing();
386 void FinishedDeserializing() override
{
387 for (size_t i
= 0; i
< Sources
.size(); ++i
)
388 Sources
[i
]->FinishedDeserializing();
391 void StartTranslationUnit(clang::ASTConsumer
*Consumer
) override
{
392 for (size_t i
= 0; i
< Sources
.size(); ++i
)
393 Sources
[i
]->StartTranslationUnit(Consumer
);
396 void PrintStats() override
;
398 clang::Module
*getModule(unsigned ID
) override
{
399 for (size_t i
= 0; i
< Sources
.size(); ++i
)
400 if (auto M
= Sources
[i
]->getModule(ID
))
405 bool layoutRecordType(
406 const clang::RecordDecl
*Record
, uint64_t &Size
, uint64_t &Alignment
,
407 llvm::DenseMap
<const clang::FieldDecl
*, uint64_t> &FieldOffsets
,
408 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
410 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
411 &VirtualBaseOffsets
) override
{
412 for (size_t i
= 0; i
< Sources
.size(); ++i
)
413 if (Sources
[i
]->layoutRecordType(Record
, Size
, Alignment
, FieldOffsets
,
414 BaseOffsets
, VirtualBaseOffsets
))
419 void getMemoryBufferSizes(MemoryBufferSizes
&sizes
) const override
{
420 for (auto &Source
: Sources
)
421 Source
->getMemoryBufferSizes(sizes
);
424 //===--------------------------------------------------------------------===//
425 // ExternalSemaSource.
426 //===--------------------------------------------------------------------===//
428 void InitializeSema(clang::Sema
&S
) override
{
429 for (auto &Source
: Sources
)
430 Source
->InitializeSema(S
);
433 void ForgetSema() override
{
434 for (auto &Source
: Sources
)
435 Source
->ForgetSema();
438 void ReadMethodPool(clang::Selector Sel
) override
{
439 for (auto &Source
: Sources
)
440 Source
->ReadMethodPool(Sel
);
443 void updateOutOfDateSelector(clang::Selector Sel
) override
{
444 for (auto &Source
: Sources
)
445 Source
->updateOutOfDateSelector(Sel
);
448 void ReadKnownNamespaces(
449 llvm::SmallVectorImpl
<clang::NamespaceDecl
*> &Namespaces
) override
{
450 for (auto &Source
: Sources
)
451 Source
->ReadKnownNamespaces(Namespaces
);
454 void ReadUndefinedButUsed(
455 llvm::MapVector
<clang::NamedDecl
*, clang::SourceLocation
> &Undefined
)
457 for (auto &Source
: Sources
)
458 Source
->ReadUndefinedButUsed(Undefined
);
461 void ReadMismatchingDeleteExpressions(
462 llvm::MapVector
<clang::FieldDecl
*,
463 llvm::SmallVector
<std::pair
<clang::SourceLocation
, bool>,
464 4>> &Exprs
) override
{
465 for (auto &Source
: Sources
)
466 Source
->ReadMismatchingDeleteExpressions(Exprs
);
469 bool LookupUnqualified(clang::LookupResult
&R
, clang::Scope
*S
) override
{
470 for (auto &Source
: Sources
) {
471 Source
->LookupUnqualified(R
, S
);
479 void ReadTentativeDefinitions(
480 llvm::SmallVectorImpl
<clang::VarDecl
*> &Defs
) override
{
481 for (auto &Source
: Sources
)
482 Source
->ReadTentativeDefinitions(Defs
);
485 void ReadUnusedFileScopedDecls(
486 llvm::SmallVectorImpl
<const clang::DeclaratorDecl
*> &Decls
) override
{
487 for (auto &Source
: Sources
)
488 Source
->ReadUnusedFileScopedDecls(Decls
);
491 void ReadDelegatingConstructors(
492 llvm::SmallVectorImpl
<clang::CXXConstructorDecl
*> &Decls
) override
{
493 for (auto &Source
: Sources
)
494 Source
->ReadDelegatingConstructors(Decls
);
497 void ReadExtVectorDecls(
498 llvm::SmallVectorImpl
<clang::TypedefNameDecl
*> &Decls
) override
{
499 for (auto &Source
: Sources
)
500 Source
->ReadExtVectorDecls(Decls
);
503 void ReadUnusedLocalTypedefNameCandidates(
504 llvm::SmallSetVector
<const clang::TypedefNameDecl
*, 4> &Decls
) override
{
505 for (auto &Source
: Sources
)
506 Source
->ReadUnusedLocalTypedefNameCandidates(Decls
);
509 void ReadReferencedSelectors(
510 llvm::SmallVectorImpl
<std::pair
<clang::Selector
, clang::SourceLocation
>>
512 for (auto &Source
: Sources
)
513 Source
->ReadReferencedSelectors(Sels
);
516 void ReadWeakUndeclaredIdentifiers(
517 llvm::SmallVectorImpl
<std::pair
<clang::IdentifierInfo
*, clang::WeakInfo
>>
519 for (auto &Source
: Sources
)
520 Source
->ReadWeakUndeclaredIdentifiers(WI
);
523 void ReadUsedVTables(
524 llvm::SmallVectorImpl
<clang::ExternalVTableUse
> &VTables
) override
{
525 for (auto &Source
: Sources
)
526 Source
->ReadUsedVTables(VTables
);
529 void ReadPendingInstantiations(
530 llvm::SmallVectorImpl
<
531 std::pair
<clang::ValueDecl
*, clang::SourceLocation
>> &Pending
)
533 for (auto &Source
: Sources
)
534 Source
->ReadPendingInstantiations(Pending
);
537 void ReadLateParsedTemplates(
538 llvm::MapVector
<const clang::FunctionDecl
*,
539 std::unique_ptr
<clang::LateParsedTemplate
>> &LPTMap
)
541 for (auto &Source
: Sources
)
542 Source
->ReadLateParsedTemplates(LPTMap
);
545 clang::TypoCorrection
546 CorrectTypo(const clang::DeclarationNameInfo
&Typo
, int LookupKind
,
547 clang::Scope
*S
, clang::CXXScopeSpec
*SS
,
548 clang::CorrectionCandidateCallback
&CCC
,
549 clang::DeclContext
*MemberContext
, bool EnteringContext
,
550 const clang::ObjCObjectPointerType
*OPT
) override
{
551 for (auto &Source
: Sources
) {
552 if (clang::TypoCorrection C
=
553 Source
->CorrectTypo(Typo
, LookupKind
, S
, SS
, CCC
,
554 MemberContext
, EnteringContext
, OPT
))
557 return clang::TypoCorrection();
560 bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc
,
561 clang::QualType T
) override
{
562 for (auto &Source
: Sources
) {
563 if (Source
->MaybeDiagnoseMissingCompleteType(Loc
, T
))
570 } // namespace lldb_private
571 #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H