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/ASTSourceDescriptor.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"
17 #include "llvm/ADT/IntrusiveRefCntPtr.h"
18 #include "llvm/Support/Casting.h"
27 namespace lldb_private
{
29 /// Wraps an ExternalASTSource into an ExternalSemaSource.
31 /// Assumes shared ownership of the underlying source.
32 class ExternalASTSourceWrapper
: public clang::ExternalSemaSource
{
33 llvm::IntrusiveRefCntPtr
<ExternalASTSource
> m_Source
;
36 explicit ExternalASTSourceWrapper(ExternalASTSource
*Source
)
38 assert(m_Source
&& "Can't wrap nullptr ExternalASTSource");
41 ~ExternalASTSourceWrapper() override
;
43 clang::Decl
*GetExternalDecl(clang::GlobalDeclID ID
) override
{
44 return m_Source
->GetExternalDecl(ID
);
47 clang::Selector
GetExternalSelector(uint32_t ID
) override
{
48 return m_Source
->GetExternalSelector(ID
);
51 uint32_t GetNumExternalSelectors() override
{
52 return m_Source
->GetNumExternalSelectors();
55 clang::Stmt
*GetExternalDeclStmt(uint64_t Offset
) override
{
56 return m_Source
->GetExternalDeclStmt(Offset
);
59 clang::CXXCtorInitializer
**
60 GetExternalCXXCtorInitializers(uint64_t Offset
) override
{
61 return m_Source
->GetExternalCXXCtorInitializers(Offset
);
64 clang::CXXBaseSpecifier
*
65 GetExternalCXXBaseSpecifiers(uint64_t Offset
) override
{
66 return m_Source
->GetExternalCXXBaseSpecifiers(Offset
);
69 void updateOutOfDateIdentifier(const clang::IdentifierInfo
&II
) override
{
70 m_Source
->updateOutOfDateIdentifier(II
);
73 bool FindExternalVisibleDeclsByName(
74 const clang::DeclContext
*DC
, clang::DeclarationName Name
,
75 const clang::DeclContext
*OriginalDC
) override
{
76 return m_Source
->FindExternalVisibleDeclsByName(DC
, Name
, OriginalDC
);
79 bool LoadExternalSpecializations(const clang::Decl
*D
,
80 bool OnlyPartial
) override
{
81 return m_Source
->LoadExternalSpecializations(D
, OnlyPartial
);
84 bool LoadExternalSpecializations(
86 llvm::ArrayRef
<clang::TemplateArgument
> TemplateArgs
) override
{
87 return m_Source
->LoadExternalSpecializations(D
, TemplateArgs
);
90 void completeVisibleDeclsMap(const clang::DeclContext
*DC
) override
{
91 m_Source
->completeVisibleDeclsMap(DC
);
94 clang::Module
*getModule(unsigned ID
) override
{
95 return m_Source
->getModule(ID
);
98 std::optional
<clang::ASTSourceDescriptor
>
99 getSourceDescriptor(unsigned ID
) override
{
100 return m_Source
->getSourceDescriptor(ID
);
103 ExtKind
hasExternalDefinitions(const clang::Decl
*D
) override
{
104 return m_Source
->hasExternalDefinitions(D
);
107 void FindExternalLexicalDecls(
108 const clang::DeclContext
*DC
,
109 llvm::function_ref
<bool(clang::Decl::Kind
)> IsKindWeWant
,
110 llvm::SmallVectorImpl
<clang::Decl
*> &Result
) override
{
111 m_Source
->FindExternalLexicalDecls(DC
, IsKindWeWant
, Result
);
115 FindFileRegionDecls(clang::FileID File
, unsigned Offset
, unsigned Length
,
116 llvm::SmallVectorImpl
<clang::Decl
*> &Decls
) override
{
117 m_Source
->FindFileRegionDecls(File
, Offset
, Length
, Decls
);
120 void CompleteRedeclChain(const clang::Decl
*D
) override
{
121 m_Source
->CompleteRedeclChain(D
);
124 void CompleteType(clang::TagDecl
*Tag
) override
{
125 m_Source
->CompleteType(Tag
);
128 void CompleteType(clang::ObjCInterfaceDecl
*Class
) override
{
129 m_Source
->CompleteType(Class
);
132 void ReadComments() override
{ m_Source
->ReadComments(); }
134 void StartedDeserializing() override
{ m_Source
->StartedDeserializing(); }
136 void FinishedDeserializing() override
{ m_Source
->FinishedDeserializing(); }
138 void StartTranslationUnit(clang::ASTConsumer
*Consumer
) override
{
139 m_Source
->StartTranslationUnit(Consumer
);
142 void PrintStats() override
;
144 bool layoutRecordType(
145 const clang::RecordDecl
*Record
, uint64_t &Size
, uint64_t &Alignment
,
146 llvm::DenseMap
<const clang::FieldDecl
*, uint64_t> &FieldOffsets
,
147 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
149 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
150 &VirtualBaseOffsets
) override
{
151 return m_Source
->layoutRecordType(Record
, Size
, Alignment
, FieldOffsets
,
152 BaseOffsets
, VirtualBaseOffsets
);
155 /// This gets called when Sema is reconciling undefined but used decls.
156 /// For LLDB's use-case, we never provide Clang with function definitions,
157 /// instead we rely on linkage names and symbol resolution to call the
158 /// correct funcitons during JITting. So this implementation clears
159 /// any "undefined" FunctionDecls that Clang found while parsing.
161 /// \param[in,out] Undefined A set of used decls for which Clang has not
162 /// been provided a definition with.
164 void ReadUndefinedButUsed(
165 llvm::MapVector
<clang::NamedDecl
*, clang::SourceLocation
> &Undefined
)
167 Undefined
.remove_if([](auto const &decl_loc_pair
) {
168 const clang::NamedDecl
*ND
= decl_loc_pair
.first
;
169 return llvm::isa_and_present
<clang::FunctionDecl
>(ND
);
174 /// Wraps an ASTConsumer into an SemaConsumer. Doesn't take ownership of the
175 /// provided consumer. If the provided ASTConsumer is also a SemaConsumer,
176 /// the wrapper will also forward SemaConsumer functions.
177 class ASTConsumerForwarder
: public clang::SemaConsumer
{
178 clang::ASTConsumer
*m_c
;
179 clang::SemaConsumer
*m_sc
;
182 ASTConsumerForwarder(clang::ASTConsumer
*c
) : m_c(c
) {
183 m_sc
= llvm::dyn_cast
<clang::SemaConsumer
>(m_c
);
186 ~ASTConsumerForwarder() override
;
188 void Initialize(clang::ASTContext
&Context
) override
{
189 m_c
->Initialize(Context
);
192 bool HandleTopLevelDecl(clang::DeclGroupRef D
) override
{
193 return m_c
->HandleTopLevelDecl(D
);
196 void HandleInlineFunctionDefinition(clang::FunctionDecl
*D
) override
{
197 m_c
->HandleInlineFunctionDefinition(D
);
200 void HandleInterestingDecl(clang::DeclGroupRef D
) override
{
201 m_c
->HandleInterestingDecl(D
);
204 void HandleTranslationUnit(clang::ASTContext
&Ctx
) override
{
205 m_c
->HandleTranslationUnit(Ctx
);
208 void HandleTagDeclDefinition(clang::TagDecl
*D
) override
{
209 m_c
->HandleTagDeclDefinition(D
);
212 void HandleTagDeclRequiredDefinition(const clang::TagDecl
*D
) override
{
213 m_c
->HandleTagDeclRequiredDefinition(D
);
216 void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl
*D
) override
{
217 m_c
->HandleCXXImplicitFunctionInstantiation(D
);
220 void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D
) override
{
221 m_c
->HandleTopLevelDeclInObjCContainer(D
);
224 void HandleImplicitImportDecl(clang::ImportDecl
*D
) override
{
225 m_c
->HandleImplicitImportDecl(D
);
228 void CompleteTentativeDefinition(clang::VarDecl
*D
) override
{
229 m_c
->CompleteTentativeDefinition(D
);
232 void AssignInheritanceModel(clang::CXXRecordDecl
*RD
) override
{
233 m_c
->AssignInheritanceModel(RD
);
236 void HandleCXXStaticMemberVarInstantiation(clang::VarDecl
*D
) override
{
237 m_c
->HandleCXXStaticMemberVarInstantiation(D
);
240 void HandleVTable(clang::CXXRecordDecl
*RD
) override
{
241 m_c
->HandleVTable(RD
);
244 clang::ASTMutationListener
*GetASTMutationListener() override
{
245 return m_c
->GetASTMutationListener();
248 clang::ASTDeserializationListener
*GetASTDeserializationListener() override
{
249 return m_c
->GetASTDeserializationListener();
252 void PrintStats() override
;
254 void InitializeSema(clang::Sema
&S
) override
{
256 m_sc
->InitializeSema(S
);
259 /// Inform the semantic consumer that Sema is no longer available.
260 void ForgetSema() override
{
265 bool shouldSkipFunctionBody(clang::Decl
*D
) override
{
266 return m_c
->shouldSkipFunctionBody(D
);
270 /// A ExternalSemaSource multiplexer that prioritizes its sources.
272 /// This ExternalSemaSource will forward all requests to its attached sources.
273 /// However, unlike a normal multiplexer it will not forward a request to all
274 /// sources, but instead give priority to certain sources. If a source with a
275 /// higher priority can fulfill a request, all sources with a lower priority
276 /// will not receive the request.
278 /// This class is mostly use to multiplex between sources of different
279 /// 'quality', e.g. a C++ modules and debug information. The C++ module will
280 /// provide more accurate replies to the requests, but might not be able to
281 /// answer all requests. The debug information will be used as a fallback then
282 /// to provide information that is not in the C++ module.
283 class SemaSourceWithPriorities
: public clang::ExternalSemaSource
{
286 /// The sources ordered in decreasing priority.
287 llvm::SmallVector
<clang::ExternalSemaSource
*, 2> Sources
;
290 /// Construct a SemaSourceWithPriorities with a 'high quality' source that
291 /// has the higher priority and a 'low quality' source that will be used
294 /// This class assumes shared ownership of the sources provided to it.
295 SemaSourceWithPriorities(clang::ExternalSemaSource
*high_quality_source
,
296 clang::ExternalSemaSource
*low_quality_source
) {
297 assert(high_quality_source
);
298 assert(low_quality_source
);
300 high_quality_source
->Retain();
301 low_quality_source
->Retain();
303 Sources
.push_back(high_quality_source
);
304 Sources
.push_back(low_quality_source
);
307 ~SemaSourceWithPriorities() override
;
309 //===--------------------------------------------------------------------===//
310 // ExternalASTSource.
311 //===--------------------------------------------------------------------===//
313 clang::Decl
*GetExternalDecl(clang::GlobalDeclID ID
) override
{
314 for (size_t i
= 0; i
< Sources
.size(); ++i
)
315 if (clang::Decl
*Result
= Sources
[i
]->GetExternalDecl(ID
))
320 bool LoadExternalSpecializations(const clang::Decl
*D
,
321 bool OnlyPartial
) override
{
322 bool newDeclFound
= false;
323 for (size_t i
= 0; i
< Sources
.size(); ++i
)
324 newDeclFound
|= Sources
[i
]->LoadExternalSpecializations(D
, OnlyPartial
);
328 bool LoadExternalSpecializations(
329 const clang::Decl
*D
,
330 llvm::ArrayRef
<clang::TemplateArgument
> TemplateArgs
) override
{
331 bool newDeclFound
= false;
332 for (size_t i
= 0; i
< Sources
.size(); ++i
)
333 newDeclFound
|= Sources
[i
]->LoadExternalSpecializations(D
, TemplateArgs
);
337 void CompleteRedeclChain(const clang::Decl
*D
) override
{
338 for (size_t i
= 0; i
< Sources
.size(); ++i
)
339 Sources
[i
]->CompleteRedeclChain(D
);
342 clang::Selector
GetExternalSelector(uint32_t ID
) override
{
344 for (size_t i
= 0; i
< Sources
.size(); ++i
) {
345 Sel
= Sources
[i
]->GetExternalSelector(ID
);
352 uint32_t GetNumExternalSelectors() override
{
353 for (size_t i
= 0; i
< Sources
.size(); ++i
)
354 if (uint32_t total
= Sources
[i
]->GetNumExternalSelectors())
359 clang::Stmt
*GetExternalDeclStmt(uint64_t Offset
) override
{
360 for (size_t i
= 0; i
< Sources
.size(); ++i
)
361 if (clang::Stmt
*Result
= Sources
[i
]->GetExternalDeclStmt(Offset
))
366 clang::CXXBaseSpecifier
*
367 GetExternalCXXBaseSpecifiers(uint64_t Offset
) override
{
368 for (size_t i
= 0; i
< Sources
.size(); ++i
)
369 if (clang::CXXBaseSpecifier
*R
=
370 Sources
[i
]->GetExternalCXXBaseSpecifiers(Offset
))
375 clang::CXXCtorInitializer
**
376 GetExternalCXXCtorInitializers(uint64_t Offset
) override
{
377 for (auto *S
: Sources
)
378 if (auto *R
= S
->GetExternalCXXCtorInitializers(Offset
))
383 ExtKind
hasExternalDefinitions(const clang::Decl
*D
) override
{
384 for (const auto &S
: Sources
)
385 if (auto EK
= S
->hasExternalDefinitions(D
))
386 if (EK
!= EK_ReplyHazy
)
391 bool FindExternalVisibleDeclsByName(
392 const clang::DeclContext
*DC
, clang::DeclarationName Name
,
393 const clang::DeclContext
*OriginalDC
) override
{
394 for (size_t i
= 0; i
< Sources
.size(); ++i
)
395 if (Sources
[i
]->FindExternalVisibleDeclsByName(DC
, Name
, OriginalDC
))
400 void completeVisibleDeclsMap(const clang::DeclContext
*DC
) override
{
401 // FIXME: Only one source should be able to complete the decls map.
402 for (size_t i
= 0; i
< Sources
.size(); ++i
)
403 Sources
[i
]->completeVisibleDeclsMap(DC
);
406 void FindExternalLexicalDecls(
407 const clang::DeclContext
*DC
,
408 llvm::function_ref
<bool(clang::Decl::Kind
)> IsKindWeWant
,
409 llvm::SmallVectorImpl
<clang::Decl
*> &Result
) override
{
410 for (size_t i
= 0; i
< Sources
.size(); ++i
) {
411 Sources
[i
]->FindExternalLexicalDecls(DC
, IsKindWeWant
, Result
);
418 FindFileRegionDecls(clang::FileID File
, unsigned Offset
, unsigned Length
,
419 llvm::SmallVectorImpl
<clang::Decl
*> &Decls
) override
{
420 for (size_t i
= 0; i
< Sources
.size(); ++i
)
421 Sources
[i
]->FindFileRegionDecls(File
, Offset
, Length
, Decls
);
424 void CompleteType(clang::TagDecl
*Tag
) override
{
425 for (clang::ExternalSemaSource
*S
: Sources
) {
426 S
->CompleteType(Tag
);
427 // Stop after the first source completed the type.
428 if (Tag
->isCompleteDefinition())
433 void CompleteType(clang::ObjCInterfaceDecl
*Class
) override
{
434 for (size_t i
= 0; i
< Sources
.size(); ++i
)
435 Sources
[i
]->CompleteType(Class
);
438 void ReadComments() override
{
439 for (size_t i
= 0; i
< Sources
.size(); ++i
)
440 Sources
[i
]->ReadComments();
443 void StartedDeserializing() override
{
444 for (size_t i
= 0; i
< Sources
.size(); ++i
)
445 Sources
[i
]->StartedDeserializing();
448 void FinishedDeserializing() override
{
449 for (size_t i
= 0; i
< Sources
.size(); ++i
)
450 Sources
[i
]->FinishedDeserializing();
453 void StartTranslationUnit(clang::ASTConsumer
*Consumer
) override
{
454 for (size_t i
= 0; i
< Sources
.size(); ++i
)
455 Sources
[i
]->StartTranslationUnit(Consumer
);
458 void PrintStats() override
;
460 clang::Module
*getModule(unsigned ID
) override
{
461 for (size_t i
= 0; i
< Sources
.size(); ++i
)
462 if (auto M
= Sources
[i
]->getModule(ID
))
467 bool layoutRecordType(
468 const clang::RecordDecl
*Record
, uint64_t &Size
, uint64_t &Alignment
,
469 llvm::DenseMap
<const clang::FieldDecl
*, uint64_t> &FieldOffsets
,
470 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
472 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
473 &VirtualBaseOffsets
) override
{
474 for (size_t i
= 0; i
< Sources
.size(); ++i
)
475 if (Sources
[i
]->layoutRecordType(Record
, Size
, Alignment
, FieldOffsets
,
476 BaseOffsets
, VirtualBaseOffsets
))
481 void getMemoryBufferSizes(MemoryBufferSizes
&sizes
) const override
{
482 for (auto &Source
: Sources
)
483 Source
->getMemoryBufferSizes(sizes
);
486 //===--------------------------------------------------------------------===//
487 // ExternalSemaSource.
488 //===--------------------------------------------------------------------===//
490 void InitializeSema(clang::Sema
&S
) override
{
491 for (auto &Source
: Sources
)
492 Source
->InitializeSema(S
);
495 void ForgetSema() override
{
496 for (auto &Source
: Sources
)
497 Source
->ForgetSema();
500 void ReadMethodPool(clang::Selector Sel
) override
{
501 for (auto &Source
: Sources
)
502 Source
->ReadMethodPool(Sel
);
505 void updateOutOfDateSelector(clang::Selector Sel
) override
{
506 for (auto &Source
: Sources
)
507 Source
->updateOutOfDateSelector(Sel
);
510 void ReadKnownNamespaces(
511 llvm::SmallVectorImpl
<clang::NamespaceDecl
*> &Namespaces
) override
{
512 for (auto &Source
: Sources
)
513 Source
->ReadKnownNamespaces(Namespaces
);
516 void ReadUndefinedButUsed(
517 llvm::MapVector
<clang::NamedDecl
*, clang::SourceLocation
> &Undefined
)
519 for (auto &Source
: Sources
)
520 Source
->ReadUndefinedButUsed(Undefined
);
523 void ReadMismatchingDeleteExpressions(
524 llvm::MapVector
<clang::FieldDecl
*,
525 llvm::SmallVector
<std::pair
<clang::SourceLocation
, bool>,
526 4>> &Exprs
) override
{
527 for (auto &Source
: Sources
)
528 Source
->ReadMismatchingDeleteExpressions(Exprs
);
531 bool LookupUnqualified(clang::LookupResult
&R
, clang::Scope
*S
) override
{
532 for (auto &Source
: Sources
) {
533 Source
->LookupUnqualified(R
, S
);
541 void ReadTentativeDefinitions(
542 llvm::SmallVectorImpl
<clang::VarDecl
*> &Defs
) override
{
543 for (auto &Source
: Sources
)
544 Source
->ReadTentativeDefinitions(Defs
);
547 void ReadUnusedFileScopedDecls(
548 llvm::SmallVectorImpl
<const clang::DeclaratorDecl
*> &Decls
) override
{
549 for (auto &Source
: Sources
)
550 Source
->ReadUnusedFileScopedDecls(Decls
);
553 void ReadDelegatingConstructors(
554 llvm::SmallVectorImpl
<clang::CXXConstructorDecl
*> &Decls
) override
{
555 for (auto &Source
: Sources
)
556 Source
->ReadDelegatingConstructors(Decls
);
559 void ReadExtVectorDecls(
560 llvm::SmallVectorImpl
<clang::TypedefNameDecl
*> &Decls
) override
{
561 for (auto &Source
: Sources
)
562 Source
->ReadExtVectorDecls(Decls
);
565 void ReadUnusedLocalTypedefNameCandidates(
566 llvm::SmallSetVector
<const clang::TypedefNameDecl
*, 4> &Decls
) override
{
567 for (auto &Source
: Sources
)
568 Source
->ReadUnusedLocalTypedefNameCandidates(Decls
);
571 void ReadReferencedSelectors(
572 llvm::SmallVectorImpl
<std::pair
<clang::Selector
, clang::SourceLocation
>>
574 for (auto &Source
: Sources
)
575 Source
->ReadReferencedSelectors(Sels
);
578 void ReadWeakUndeclaredIdentifiers(
579 llvm::SmallVectorImpl
<std::pair
<clang::IdentifierInfo
*, clang::WeakInfo
>>
581 for (auto &Source
: Sources
)
582 Source
->ReadWeakUndeclaredIdentifiers(WI
);
585 void ReadUsedVTables(
586 llvm::SmallVectorImpl
<clang::ExternalVTableUse
> &VTables
) override
{
587 for (auto &Source
: Sources
)
588 Source
->ReadUsedVTables(VTables
);
591 void ReadPendingInstantiations(
592 llvm::SmallVectorImpl
<
593 std::pair
<clang::ValueDecl
*, clang::SourceLocation
>> &Pending
)
595 for (auto &Source
: Sources
)
596 Source
->ReadPendingInstantiations(Pending
);
599 void ReadLateParsedTemplates(
600 llvm::MapVector
<const clang::FunctionDecl
*,
601 std::unique_ptr
<clang::LateParsedTemplate
>> &LPTMap
)
603 for (auto &Source
: Sources
)
604 Source
->ReadLateParsedTemplates(LPTMap
);
607 clang::TypoCorrection
608 CorrectTypo(const clang::DeclarationNameInfo
&Typo
, int LookupKind
,
609 clang::Scope
*S
, clang::CXXScopeSpec
*SS
,
610 clang::CorrectionCandidateCallback
&CCC
,
611 clang::DeclContext
*MemberContext
, bool EnteringContext
,
612 const clang::ObjCObjectPointerType
*OPT
) override
{
613 for (auto &Source
: Sources
) {
614 if (clang::TypoCorrection C
=
615 Source
->CorrectTypo(Typo
, LookupKind
, S
, SS
, CCC
,
616 MemberContext
, EnteringContext
, OPT
))
619 return clang::TypoCorrection();
622 bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc
,
623 clang::QualType T
) override
{
624 for (auto &Source
: Sources
) {
625 if (Source
->MaybeDiagnoseMissingCompleteType(Loc
, T
))
632 } // namespace lldb_private
633 #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H