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 
18 namespace lldb_private {
19 
20 /// Wraps an ExternalASTSource into an ExternalSemaSource. Doesn't take
21 /// ownership of the provided source.
22 class ExternalASTSourceWrapper : public clang::ExternalSemaSource {
23   ExternalASTSource *m_Source;
24 
25 public:
26   ExternalASTSourceWrapper(ExternalASTSource *Source) : m_Source(Source) {
27     assert(m_Source && "Can't wrap nullptr ExternalASTSource");
28   }
29 
30   ~ExternalASTSourceWrapper() override;
31 
32   clang::Decl *GetExternalDecl(uint32_t ID) override {
33     return m_Source->GetExternalDecl(ID);
34   }
35 
36   clang::Selector GetExternalSelector(uint32_t ID) override {
37     return m_Source->GetExternalSelector(ID);
38   }
39 
40   uint32_t GetNumExternalSelectors() override {
41     return m_Source->GetNumExternalSelectors();
42   }
43 
44   clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {
45     return m_Source->GetExternalDeclStmt(Offset);
46   }
47 
48   clang::CXXCtorInitializer **
49   GetExternalCXXCtorInitializers(uint64_t Offset) override {
50     return m_Source->GetExternalCXXCtorInitializers(Offset);
51   }
52 
53   clang::CXXBaseSpecifier *
54   GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
55     return m_Source->GetExternalCXXBaseSpecifiers(Offset);
56   }
57 
58   void updateOutOfDateIdentifier(clang::IdentifierInfo &II) override {
59     m_Source->updateOutOfDateIdentifier(II);
60   }
61 
62   bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
63                                       clang::DeclarationName Name) override {
64     return m_Source->FindExternalVisibleDeclsByName(DC, Name);
65   }
66 
67   void completeVisibleDeclsMap(const clang::DeclContext *DC) override {
68     m_Source->completeVisibleDeclsMap(DC);
69   }
70 
71   clang::Module *getModule(unsigned ID) override {
72     return m_Source->getModule(ID);
73   }
74 
75   llvm::Optional<clang::ASTSourceDescriptor>
76   getSourceDescriptor(unsigned ID) override {
77     return m_Source->getSourceDescriptor(ID);
78   }
79 
80   ExtKind hasExternalDefinitions(const clang::Decl *D) override {
81     return m_Source->hasExternalDefinitions(D);
82   }
83 
84   void FindExternalLexicalDecls(
85       const clang::DeclContext *DC,
86       llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
87       llvm::SmallVectorImpl<clang::Decl *> &Result) override {
88     m_Source->FindExternalLexicalDecls(DC, IsKindWeWant, Result);
89   }
90 
91   void
92   FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,
93                       llvm::SmallVectorImpl<clang::Decl *> &Decls) override {
94     m_Source->FindFileRegionDecls(File, Offset, Length, Decls);
95   }
96 
97   void CompleteRedeclChain(const clang::Decl *D) override {
98     m_Source->CompleteRedeclChain(D);
99   }
100 
101   void CompleteType(clang::TagDecl *Tag) override {
102     m_Source->CompleteType(Tag);
103   }
104 
105   void CompleteType(clang::ObjCInterfaceDecl *Class) override {
106     m_Source->CompleteType(Class);
107   }
108 
109   void ReadComments() override { m_Source->ReadComments(); }
110 
111   void StartedDeserializing() override { m_Source->StartedDeserializing(); }
112 
113   void FinishedDeserializing() override { m_Source->FinishedDeserializing(); }
114 
115   void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
116     m_Source->StartTranslationUnit(Consumer);
117   }
118 
119   void PrintStats() override;
120 
121   bool layoutRecordType(
122       const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
123       llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
124       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
125           &BaseOffsets,
126       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
127           &VirtualBaseOffsets) override {
128     return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets,
129                                       BaseOffsets, VirtualBaseOffsets);
130   }
131 };
132 
133 /// Wraps an ASTConsumer into an SemaConsumer. Doesn't take ownership of the
134 /// provided consumer. If the provided ASTConsumer is also a SemaConsumer,
135 /// the wrapper will also forward SemaConsumer functions.
136 class ASTConsumerForwarder : public clang::SemaConsumer {
137   clang::ASTConsumer *m_c;
138   clang::SemaConsumer *m_sc;
139 
140 public:
141   ASTConsumerForwarder(clang::ASTConsumer *c) : m_c(c) {
142     m_sc = llvm::dyn_cast<clang::SemaConsumer>(m_c);
143   }
144 
145   ~ASTConsumerForwarder() override;
146 
147   void Initialize(clang::ASTContext &Context) override {
148     m_c->Initialize(Context);
149   }
150 
151   bool HandleTopLevelDecl(clang::DeclGroupRef D) override {
152     return m_c->HandleTopLevelDecl(D);
153   }
154 
155   void HandleInlineFunctionDefinition(clang::FunctionDecl *D) override {
156     m_c->HandleInlineFunctionDefinition(D);
157   }
158 
159   void HandleInterestingDecl(clang::DeclGroupRef D) override {
160     m_c->HandleInterestingDecl(D);
161   }
162 
163   void HandleTranslationUnit(clang::ASTContext &Ctx) override {
164     m_c->HandleTranslationUnit(Ctx);
165   }
166 
167   void HandleTagDeclDefinition(clang::TagDecl *D) override {
168     m_c->HandleTagDeclDefinition(D);
169   }
170 
171   void HandleTagDeclRequiredDefinition(const clang::TagDecl *D) override {
172     m_c->HandleTagDeclRequiredDefinition(D);
173   }
174 
175   void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl *D) override {
176     m_c->HandleCXXImplicitFunctionInstantiation(D);
177   }
178 
179   void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D) override {
180     m_c->HandleTopLevelDeclInObjCContainer(D);
181   }
182 
183   void HandleImplicitImportDecl(clang::ImportDecl *D) override {
184     m_c->HandleImplicitImportDecl(D);
185   }
186 
187   void CompleteTentativeDefinition(clang::VarDecl *D) override {
188     m_c->CompleteTentativeDefinition(D);
189   }
190 
191   void AssignInheritanceModel(clang::CXXRecordDecl *RD) override {
192     m_c->AssignInheritanceModel(RD);
193   }
194 
195   void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *D) override {
196     m_c->HandleCXXStaticMemberVarInstantiation(D);
197   }
198 
199   void HandleVTable(clang::CXXRecordDecl *RD) override {
200     m_c->HandleVTable(RD);
201   }
202 
203   clang::ASTMutationListener *GetASTMutationListener() override {
204     return m_c->GetASTMutationListener();
205   }
206 
207   clang::ASTDeserializationListener *GetASTDeserializationListener() override {
208     return m_c->GetASTDeserializationListener();
209   }
210 
211   void PrintStats() override;
212 
213   void InitializeSema(clang::Sema &S) override {
214     if (m_sc)
215       m_sc->InitializeSema(S);
216   }
217 
218   /// Inform the semantic consumer that Sema is no longer available.
219   void ForgetSema() override {
220     if (m_sc)
221       m_sc->ForgetSema();
222   }
223 
224   bool shouldSkipFunctionBody(clang::Decl *D) override {
225     return m_c->shouldSkipFunctionBody(D);
226   }
227 };
228 
229 /// A ExternalSemaSource multiplexer that prioritizes its sources.
230 ///
231 /// This ExternalSemaSource will forward all requests to its attached sources.
232 /// However, unlike a normal multiplexer it will not forward a request to all
233 /// sources, but instead give priority to certain sources. If a source with a
234 /// higher priority can fulfill a request, all sources with a lower priority
235 /// will not receive the request.
236 ///
237 /// This class is mostly use to multiplex between sources of different
238 /// 'quality', e.g. a C++ modules and debug information. The C++ module will
239 /// provide more accurate replies to the requests, but might not be able to
240 /// answer all requests. The debug information will be used as a fallback then
241 /// to provide information that is not in the C++ module.
242 class SemaSourceWithPriorities : public clang::ExternalSemaSource {
243 
244 private:
245   /// The sources ordered in decreasing priority.
246   llvm::SmallVector<clang::ExternalSemaSource *, 2> Sources;
247 
248 public:
249   /// Construct a SemaSourceWithPriorities with a 'high quality' source that
250   /// has the higher priority and a 'low quality' source that will be used
251   /// as a fallback.
252   SemaSourceWithPriorities(clang::ExternalSemaSource &high_quality_source,
253                            clang::ExternalSemaSource &low_quality_source) {
254     Sources.push_back(&high_quality_source);
255     Sources.push_back(&low_quality_source);
256   }
257 
258   ~SemaSourceWithPriorities() override;
259 
260   void addSource(clang::ExternalSemaSource &source) {
261     Sources.push_back(&source);
262   }
263 
264   //===--------------------------------------------------------------------===//
265   // ExternalASTSource.
266   //===--------------------------------------------------------------------===//
267 
268   clang::Decl *GetExternalDecl(uint32_t ID) override {
269     for (size_t i = 0; i < Sources.size(); ++i)
270       if (clang::Decl *Result = Sources[i]->GetExternalDecl(ID))
271         return Result;
272     return nullptr;
273   }
274 
275   void CompleteRedeclChain(const clang::Decl *D) override {
276     for (size_t i = 0; i < Sources.size(); ++i)
277       Sources[i]->CompleteRedeclChain(D);
278   }
279 
280   clang::Selector GetExternalSelector(uint32_t ID) override {
281     clang::Selector Sel;
282     for (size_t i = 0; i < Sources.size(); ++i) {
283       Sel = Sources[i]->GetExternalSelector(ID);
284       if (!Sel.isNull())
285         return Sel;
286     }
287     return Sel;
288   }
289 
290   uint32_t GetNumExternalSelectors() override {
291     for (size_t i = 0; i < Sources.size(); ++i)
292       if (uint32_t total = Sources[i]->GetNumExternalSelectors())
293         return total;
294     return 0;
295   }
296 
297   clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {
298     for (size_t i = 0; i < Sources.size(); ++i)
299       if (clang::Stmt *Result = Sources[i]->GetExternalDeclStmt(Offset))
300         return Result;
301     return nullptr;
302   }
303 
304   clang::CXXBaseSpecifier *
305   GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
306     for (size_t i = 0; i < Sources.size(); ++i)
307       if (clang::CXXBaseSpecifier *R =
308               Sources[i]->GetExternalCXXBaseSpecifiers(Offset))
309         return R;
310     return nullptr;
311   }
312 
313   clang::CXXCtorInitializer **
314   GetExternalCXXCtorInitializers(uint64_t Offset) override {
315     for (auto *S : Sources)
316       if (auto *R = S->GetExternalCXXCtorInitializers(Offset))
317         return R;
318     return nullptr;
319   }
320 
321   ExtKind hasExternalDefinitions(const clang::Decl *D) override {
322     for (const auto &S : Sources)
323       if (auto EK = S->hasExternalDefinitions(D))
324         if (EK != EK_ReplyHazy)
325           return EK;
326     return EK_ReplyHazy;
327   }
328 
329   bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
330                                       clang::DeclarationName Name) override {
331     for (size_t i = 0; i < Sources.size(); ++i)
332       if (Sources[i]->FindExternalVisibleDeclsByName(DC, Name))
333         return true;
334     return false;
335   }
336 
337   void completeVisibleDeclsMap(const clang::DeclContext *DC) override {
338     // FIXME: Only one source should be able to complete the decls map.
339     for (size_t i = 0; i < Sources.size(); ++i)
340       Sources[i]->completeVisibleDeclsMap(DC);
341   }
342 
343   void FindExternalLexicalDecls(
344       const clang::DeclContext *DC,
345       llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
346       llvm::SmallVectorImpl<clang::Decl *> &Result) override {
347     for (size_t i = 0; i < Sources.size(); ++i) {
348       Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result);
349       if (!Result.empty())
350         return;
351     }
352   }
353 
354   void
355   FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,
356                       llvm::SmallVectorImpl<clang::Decl *> &Decls) override {
357     for (size_t i = 0; i < Sources.size(); ++i)
358       Sources[i]->FindFileRegionDecls(File, Offset, Length, Decls);
359   }
360 
361   void CompleteType(clang::TagDecl *Tag) override {
362     for (clang::ExternalSemaSource *S : Sources) {
363       S->CompleteType(Tag);
364       // Stop after the first source completed the type.
365       if (Tag->isCompleteDefinition())
366         break;
367     }
368   }
369 
370   void CompleteType(clang::ObjCInterfaceDecl *Class) override {
371     for (size_t i = 0; i < Sources.size(); ++i)
372       Sources[i]->CompleteType(Class);
373   }
374 
375   void ReadComments() override {
376     for (size_t i = 0; i < Sources.size(); ++i)
377       Sources[i]->ReadComments();
378   }
379 
380   void StartedDeserializing() override {
381     for (size_t i = 0; i < Sources.size(); ++i)
382       Sources[i]->StartedDeserializing();
383   }
384 
385   void FinishedDeserializing() override {
386     for (size_t i = 0; i < Sources.size(); ++i)
387       Sources[i]->FinishedDeserializing();
388   }
389 
390   void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
391     for (size_t i = 0; i < Sources.size(); ++i)
392       Sources[i]->StartTranslationUnit(Consumer);
393   }
394 
395   void PrintStats() override;
396 
397   clang::Module *getModule(unsigned ID) override {
398     for (size_t i = 0; i < Sources.size(); ++i)
399       if (auto M = Sources[i]->getModule(ID))
400         return M;
401     return nullptr;
402   }
403 
404   bool layoutRecordType(
405       const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
406       llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
407       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
408           &BaseOffsets,
409       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
410           &VirtualBaseOffsets) override {
411     for (size_t i = 0; i < Sources.size(); ++i)
412       if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets,
413                                        BaseOffsets, VirtualBaseOffsets))
414         return true;
415     return false;
416   }
417 
418   void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override {
419     for (auto &Source : Sources)
420       Source->getMemoryBufferSizes(sizes);
421   }
422 
423   //===--------------------------------------------------------------------===//
424   // ExternalSemaSource.
425   //===--------------------------------------------------------------------===//
426 
427   void InitializeSema(clang::Sema &S) override {
428     for (auto &Source : Sources)
429       Source->InitializeSema(S);
430   }
431 
432   void ForgetSema() override {
433     for (auto &Source : Sources)
434       Source->ForgetSema();
435   }
436 
437   void ReadMethodPool(clang::Selector Sel) override {
438     for (auto &Source : Sources)
439       Source->ReadMethodPool(Sel);
440   }
441 
442   void updateOutOfDateSelector(clang::Selector Sel) override {
443     for (auto &Source : Sources)
444       Source->updateOutOfDateSelector(Sel);
445   }
446 
447   void ReadKnownNamespaces(
448       llvm::SmallVectorImpl<clang::NamespaceDecl *> &Namespaces) override {
449     for (auto &Source : Sources)
450       Source->ReadKnownNamespaces(Namespaces);
451   }
452 
453   void ReadUndefinedButUsed(
454       llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined)
455       override {
456     for (auto &Source : Sources)
457       Source->ReadUndefinedButUsed(Undefined);
458   }
459 
460   void ReadMismatchingDeleteExpressions(
461       llvm::MapVector<clang::FieldDecl *,
462                       llvm::SmallVector<std::pair<clang::SourceLocation, bool>,
463                                         4>> &Exprs) override {
464     for (auto &Source : Sources)
465       Source->ReadMismatchingDeleteExpressions(Exprs);
466   }
467 
468   bool LookupUnqualified(clang::LookupResult &R, clang::Scope *S) override {
469     for (auto &Source : Sources) {
470       Source->LookupUnqualified(R, S);
471       if (!R.empty())
472         break;
473     }
474 
475     return !R.empty();
476   }
477 
478   void ReadTentativeDefinitions(
479       llvm::SmallVectorImpl<clang::VarDecl *> &Defs) override {
480     for (auto &Source : Sources)
481       Source->ReadTentativeDefinitions(Defs);
482   }
483 
484   void ReadUnusedFileScopedDecls(
485       llvm::SmallVectorImpl<const clang::DeclaratorDecl *> &Decls) override {
486     for (auto &Source : Sources)
487       Source->ReadUnusedFileScopedDecls(Decls);
488   }
489 
490   void ReadDelegatingConstructors(
491       llvm::SmallVectorImpl<clang::CXXConstructorDecl *> &Decls) override {
492     for (auto &Source : Sources)
493       Source->ReadDelegatingConstructors(Decls);
494   }
495 
496   void ReadExtVectorDecls(
497       llvm::SmallVectorImpl<clang::TypedefNameDecl *> &Decls) override {
498     for (auto &Source : Sources)
499       Source->ReadExtVectorDecls(Decls);
500   }
501 
502   void ReadUnusedLocalTypedefNameCandidates(
503       llvm::SmallSetVector<const clang::TypedefNameDecl *, 4> &Decls) override {
504     for (auto &Source : Sources)
505       Source->ReadUnusedLocalTypedefNameCandidates(Decls);
506   }
507 
508   void ReadReferencedSelectors(
509       llvm::SmallVectorImpl<std::pair<clang::Selector, clang::SourceLocation>>
510           &Sels) override {
511     for (auto &Source : Sources)
512       Source->ReadReferencedSelectors(Sels);
513   }
514 
515   void ReadWeakUndeclaredIdentifiers(
516       llvm::SmallVectorImpl<std::pair<clang::IdentifierInfo *, clang::WeakInfo>>
517           &WI) override {
518     for (auto &Source : Sources)
519       Source->ReadWeakUndeclaredIdentifiers(WI);
520   }
521 
522   void ReadUsedVTables(
523       llvm::SmallVectorImpl<clang::ExternalVTableUse> &VTables) override {
524     for (auto &Source : Sources)
525       Source->ReadUsedVTables(VTables);
526   }
527 
528   void ReadPendingInstantiations(
529       llvm::SmallVectorImpl<
530           std::pair<clang::ValueDecl *, clang::SourceLocation>> &Pending)
531       override {
532     for (auto &Source : Sources)
533       Source->ReadPendingInstantiations(Pending);
534   }
535 
536   void ReadLateParsedTemplates(
537       llvm::MapVector<const clang::FunctionDecl *,
538                       std::unique_ptr<clang::LateParsedTemplate>> &LPTMap)
539       override {
540     for (auto &Source : Sources)
541       Source->ReadLateParsedTemplates(LPTMap);
542   }
543 
544   clang::TypoCorrection
545   CorrectTypo(const clang::DeclarationNameInfo &Typo, int LookupKind,
546               clang::Scope *S, clang::CXXScopeSpec *SS,
547               clang::CorrectionCandidateCallback &CCC,
548               clang::DeclContext *MemberContext, bool EnteringContext,
549               const clang::ObjCObjectPointerType *OPT) override {
550     for (auto &Source : Sources) {
551       if (clang::TypoCorrection C =
552               Source->CorrectTypo(Typo, LookupKind, S, SS, CCC,
553                                       MemberContext, EnteringContext, OPT))
554         return C;
555     }
556     return clang::TypoCorrection();
557   }
558 
559   bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc,
560                                         clang::QualType T) override {
561     for (auto &Source : Sources) {
562       if (Source->MaybeDiagnoseMissingCompleteType(Loc, T))
563         return true;
564     }
565     return false;
566   }
567 };
568 
569 } // namespace lldb_private
570 #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H
571