1 //===-- ASTUtils.h ----------------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H
10 #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H
11 
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"
17 #include <optional>
18 
19 namespace lldb_private {
20 
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;
25 
26 public:
27   ExternalASTSourceWrapper(ExternalASTSource *Source) : m_Source(Source) {
28     assert(m_Source && "Can't wrap nullptr ExternalASTSource");
29   }
30 
31   ~ExternalASTSourceWrapper() override;
32 
33   clang::Decl *GetExternalDecl(uint32_t ID) override {
34     return m_Source->GetExternalDecl(ID);
35   }
36 
37   clang::Selector GetExternalSelector(uint32_t ID) override {
38     return m_Source->GetExternalSelector(ID);
39   }
40 
41   uint32_t GetNumExternalSelectors() override {
42     return m_Source->GetNumExternalSelectors();
43   }
44 
45   clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {
46     return m_Source->GetExternalDeclStmt(Offset);
47   }
48 
49   clang::CXXCtorInitializer **
50   GetExternalCXXCtorInitializers(uint64_t Offset) override {
51     return m_Source->GetExternalCXXCtorInitializers(Offset);
52   }
53 
54   clang::CXXBaseSpecifier *
55   GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
56     return m_Source->GetExternalCXXBaseSpecifiers(Offset);
57   }
58 
59   void updateOutOfDateIdentifier(clang::IdentifierInfo &II) override {
60     m_Source->updateOutOfDateIdentifier(II);
61   }
62 
63   bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
64                                       clang::DeclarationName Name) override {
65     return m_Source->FindExternalVisibleDeclsByName(DC, Name);
66   }
67 
68   void completeVisibleDeclsMap(const clang::DeclContext *DC) override {
69     m_Source->completeVisibleDeclsMap(DC);
70   }
71 
72   clang::Module *getModule(unsigned ID) override {
73     return m_Source->getModule(ID);
74   }
75 
76   std::optional<clang::ASTSourceDescriptor>
77   getSourceDescriptor(unsigned ID) override {
78     return m_Source->getSourceDescriptor(ID);
79   }
80 
81   ExtKind hasExternalDefinitions(const clang::Decl *D) override {
82     return m_Source->hasExternalDefinitions(D);
83   }
84 
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);
90   }
91 
92   void
93   FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,
94                       llvm::SmallVectorImpl<clang::Decl *> &Decls) override {
95     m_Source->FindFileRegionDecls(File, Offset, Length, Decls);
96   }
97 
98   void CompleteRedeclChain(const clang::Decl *D) override {
99     m_Source->CompleteRedeclChain(D);
100   }
101 
102   void CompleteType(clang::TagDecl *Tag) override {
103     m_Source->CompleteType(Tag);
104   }
105 
106   void CompleteType(clang::ObjCInterfaceDecl *Class) override {
107     m_Source->CompleteType(Class);
108   }
109 
110   void ReadComments() override { m_Source->ReadComments(); }
111 
112   void StartedDeserializing() override { m_Source->StartedDeserializing(); }
113 
114   void FinishedDeserializing() override { m_Source->FinishedDeserializing(); }
115 
116   void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
117     m_Source->StartTranslationUnit(Consumer);
118   }
119 
120   void PrintStats() override;
121 
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>
126           &BaseOffsets,
127       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
128           &VirtualBaseOffsets) override {
129     return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets,
130                                       BaseOffsets, VirtualBaseOffsets);
131   }
132 };
133 
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;
140 
141 public:
142   ASTConsumerForwarder(clang::ASTConsumer *c) : m_c(c) {
143     m_sc = llvm::dyn_cast<clang::SemaConsumer>(m_c);
144   }
145 
146   ~ASTConsumerForwarder() override;
147 
148   void Initialize(clang::ASTContext &Context) override {
149     m_c->Initialize(Context);
150   }
151 
152   bool HandleTopLevelDecl(clang::DeclGroupRef D) override {
153     return m_c->HandleTopLevelDecl(D);
154   }
155 
156   void HandleInlineFunctionDefinition(clang::FunctionDecl *D) override {
157     m_c->HandleInlineFunctionDefinition(D);
158   }
159 
160   void HandleInterestingDecl(clang::DeclGroupRef D) override {
161     m_c->HandleInterestingDecl(D);
162   }
163 
164   void HandleTranslationUnit(clang::ASTContext &Ctx) override {
165     m_c->HandleTranslationUnit(Ctx);
166   }
167 
168   void HandleTagDeclDefinition(clang::TagDecl *D) override {
169     m_c->HandleTagDeclDefinition(D);
170   }
171 
172   void HandleTagDeclRequiredDefinition(const clang::TagDecl *D) override {
173     m_c->HandleTagDeclRequiredDefinition(D);
174   }
175 
176   void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl *D) override {
177     m_c->HandleCXXImplicitFunctionInstantiation(D);
178   }
179 
180   void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D) override {
181     m_c->HandleTopLevelDeclInObjCContainer(D);
182   }
183 
184   void HandleImplicitImportDecl(clang::ImportDecl *D) override {
185     m_c->HandleImplicitImportDecl(D);
186   }
187 
188   void CompleteTentativeDefinition(clang::VarDecl *D) override {
189     m_c->CompleteTentativeDefinition(D);
190   }
191 
192   void AssignInheritanceModel(clang::CXXRecordDecl *RD) override {
193     m_c->AssignInheritanceModel(RD);
194   }
195 
196   void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *D) override {
197     m_c->HandleCXXStaticMemberVarInstantiation(D);
198   }
199 
200   void HandleVTable(clang::CXXRecordDecl *RD) override {
201     m_c->HandleVTable(RD);
202   }
203 
204   clang::ASTMutationListener *GetASTMutationListener() override {
205     return m_c->GetASTMutationListener();
206   }
207 
208   clang::ASTDeserializationListener *GetASTDeserializationListener() override {
209     return m_c->GetASTDeserializationListener();
210   }
211 
212   void PrintStats() override;
213 
214   void InitializeSema(clang::Sema &S) override {
215     if (m_sc)
216       m_sc->InitializeSema(S);
217   }
218 
219   /// Inform the semantic consumer that Sema is no longer available.
220   void ForgetSema() override {
221     if (m_sc)
222       m_sc->ForgetSema();
223   }
224 
225   bool shouldSkipFunctionBody(clang::Decl *D) override {
226     return m_c->shouldSkipFunctionBody(D);
227   }
228 };
229 
230 /// A ExternalSemaSource multiplexer that prioritizes its sources.
231 ///
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.
237 ///
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 {
244 
245 private:
246   /// The sources ordered in decreasing priority.
247   llvm::SmallVector<clang::ExternalSemaSource *, 2> Sources;
248 
249 public:
250   /// Construct a SemaSourceWithPriorities with a 'high quality' source that
251   /// has the higher priority and a 'low quality' source that will be used
252   /// as a fallback.
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);
257   }
258 
259   ~SemaSourceWithPriorities() override;
260 
261   void addSource(clang::ExternalSemaSource &source) {
262     Sources.push_back(&source);
263   }
264 
265   //===--------------------------------------------------------------------===//
266   // ExternalASTSource.
267   //===--------------------------------------------------------------------===//
268 
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))
272         return Result;
273     return nullptr;
274   }
275 
276   void CompleteRedeclChain(const clang::Decl *D) override {
277     for (size_t i = 0; i < Sources.size(); ++i)
278       Sources[i]->CompleteRedeclChain(D);
279   }
280 
281   clang::Selector GetExternalSelector(uint32_t ID) override {
282     clang::Selector Sel;
283     for (size_t i = 0; i < Sources.size(); ++i) {
284       Sel = Sources[i]->GetExternalSelector(ID);
285       if (!Sel.isNull())
286         return Sel;
287     }
288     return Sel;
289   }
290 
291   uint32_t GetNumExternalSelectors() override {
292     for (size_t i = 0; i < Sources.size(); ++i)
293       if (uint32_t total = Sources[i]->GetNumExternalSelectors())
294         return total;
295     return 0;
296   }
297 
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))
301         return Result;
302     return nullptr;
303   }
304 
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))
310         return R;
311     return nullptr;
312   }
313 
314   clang::CXXCtorInitializer **
315   GetExternalCXXCtorInitializers(uint64_t Offset) override {
316     for (auto *S : Sources)
317       if (auto *R = S->GetExternalCXXCtorInitializers(Offset))
318         return R;
319     return nullptr;
320   }
321 
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)
326           return EK;
327     return EK_ReplyHazy;
328   }
329 
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))
334         return true;
335     return false;
336   }
337 
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);
342   }
343 
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);
350       if (!Result.empty())
351         return;
352     }
353   }
354 
355   void
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);
360   }
361 
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())
367         break;
368     }
369   }
370 
371   void CompleteType(clang::ObjCInterfaceDecl *Class) override {
372     for (size_t i = 0; i < Sources.size(); ++i)
373       Sources[i]->CompleteType(Class);
374   }
375 
376   void ReadComments() override {
377     for (size_t i = 0; i < Sources.size(); ++i)
378       Sources[i]->ReadComments();
379   }
380 
381   void StartedDeserializing() override {
382     for (size_t i = 0; i < Sources.size(); ++i)
383       Sources[i]->StartedDeserializing();
384   }
385 
386   void FinishedDeserializing() override {
387     for (size_t i = 0; i < Sources.size(); ++i)
388       Sources[i]->FinishedDeserializing();
389   }
390 
391   void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
392     for (size_t i = 0; i < Sources.size(); ++i)
393       Sources[i]->StartTranslationUnit(Consumer);
394   }
395 
396   void PrintStats() override;
397 
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))
401         return M;
402     return nullptr;
403   }
404 
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>
409           &BaseOffsets,
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))
415         return true;
416     return false;
417   }
418 
419   void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override {
420     for (auto &Source : Sources)
421       Source->getMemoryBufferSizes(sizes);
422   }
423 
424   //===--------------------------------------------------------------------===//
425   // ExternalSemaSource.
426   //===--------------------------------------------------------------------===//
427 
428   void InitializeSema(clang::Sema &S) override {
429     for (auto &Source : Sources)
430       Source->InitializeSema(S);
431   }
432 
433   void ForgetSema() override {
434     for (auto &Source : Sources)
435       Source->ForgetSema();
436   }
437 
438   void ReadMethodPool(clang::Selector Sel) override {
439     for (auto &Source : Sources)
440       Source->ReadMethodPool(Sel);
441   }
442 
443   void updateOutOfDateSelector(clang::Selector Sel) override {
444     for (auto &Source : Sources)
445       Source->updateOutOfDateSelector(Sel);
446   }
447 
448   void ReadKnownNamespaces(
449       llvm::SmallVectorImpl<clang::NamespaceDecl *> &Namespaces) override {
450     for (auto &Source : Sources)
451       Source->ReadKnownNamespaces(Namespaces);
452   }
453 
454   void ReadUndefinedButUsed(
455       llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined)
456       override {
457     for (auto &Source : Sources)
458       Source->ReadUndefinedButUsed(Undefined);
459   }
460 
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);
467   }
468 
469   bool LookupUnqualified(clang::LookupResult &R, clang::Scope *S) override {
470     for (auto &Source : Sources) {
471       Source->LookupUnqualified(R, S);
472       if (!R.empty())
473         break;
474     }
475 
476     return !R.empty();
477   }
478 
479   void ReadTentativeDefinitions(
480       llvm::SmallVectorImpl<clang::VarDecl *> &Defs) override {
481     for (auto &Source : Sources)
482       Source->ReadTentativeDefinitions(Defs);
483   }
484 
485   void ReadUnusedFileScopedDecls(
486       llvm::SmallVectorImpl<const clang::DeclaratorDecl *> &Decls) override {
487     for (auto &Source : Sources)
488       Source->ReadUnusedFileScopedDecls(Decls);
489   }
490 
491   void ReadDelegatingConstructors(
492       llvm::SmallVectorImpl<clang::CXXConstructorDecl *> &Decls) override {
493     for (auto &Source : Sources)
494       Source->ReadDelegatingConstructors(Decls);
495   }
496 
497   void ReadExtVectorDecls(
498       llvm::SmallVectorImpl<clang::TypedefNameDecl *> &Decls) override {
499     for (auto &Source : Sources)
500       Source->ReadExtVectorDecls(Decls);
501   }
502 
503   void ReadUnusedLocalTypedefNameCandidates(
504       llvm::SmallSetVector<const clang::TypedefNameDecl *, 4> &Decls) override {
505     for (auto &Source : Sources)
506       Source->ReadUnusedLocalTypedefNameCandidates(Decls);
507   }
508 
509   void ReadReferencedSelectors(
510       llvm::SmallVectorImpl<std::pair<clang::Selector, clang::SourceLocation>>
511           &Sels) override {
512     for (auto &Source : Sources)
513       Source->ReadReferencedSelectors(Sels);
514   }
515 
516   void ReadWeakUndeclaredIdentifiers(
517       llvm::SmallVectorImpl<std::pair<clang::IdentifierInfo *, clang::WeakInfo>>
518           &WI) override {
519     for (auto &Source : Sources)
520       Source->ReadWeakUndeclaredIdentifiers(WI);
521   }
522 
523   void ReadUsedVTables(
524       llvm::SmallVectorImpl<clang::ExternalVTableUse> &VTables) override {
525     for (auto &Source : Sources)
526       Source->ReadUsedVTables(VTables);
527   }
528 
529   void ReadPendingInstantiations(
530       llvm::SmallVectorImpl<
531           std::pair<clang::ValueDecl *, clang::SourceLocation>> &Pending)
532       override {
533     for (auto &Source : Sources)
534       Source->ReadPendingInstantiations(Pending);
535   }
536 
537   void ReadLateParsedTemplates(
538       llvm::MapVector<const clang::FunctionDecl *,
539                       std::unique_ptr<clang::LateParsedTemplate>> &LPTMap)
540       override {
541     for (auto &Source : Sources)
542       Source->ReadLateParsedTemplates(LPTMap);
543   }
544 
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))
555         return C;
556     }
557     return clang::TypoCorrection();
558   }
559 
560   bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc,
561                                         clang::QualType T) override {
562     for (auto &Source : Sources) {
563       if (Source->MaybeDiagnoseMissingCompleteType(Loc, T))
564         return true;
565     }
566     return false;
567   }
568 };
569 
570 } // namespace lldb_private
571 #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H
572