1181344Sdfr//===-- ASTUtils.h ----------------------------------------------*- C++ -*-===//
2181344Sdfr//
3208291Suqs// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4181344Sdfr// See https://llvm.org/LICENSE.txt for license information.
5181344Sdfr// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6181344Sdfr//
7181344Sdfr//===----------------------------------------------------------------------===//
8181344Sdfr
9181344Sdfr#ifndef liblldb_ASTUtils_h_
10181344Sdfr#define liblldb_ASTUtils_h_
11181344Sdfr
12181344Sdfr#include "clang/Sema/Lookup.h"
13181344Sdfr#include "clang/Sema/MultiplexExternalSemaSource.h"
14181344Sdfr#include "clang/Sema/Sema.h"
15181344Sdfr#include "clang/Sema/SemaConsumer.h"
16181344Sdfr
17181344Sdfrnamespace lldb_private {
18181344Sdfr
19181344Sdfr/// Wraps an ExternalASTSource into an ExternalSemaSource. Doesn't take
20181344Sdfr/// ownership of the provided source.
21181344Sdfrclass ExternalASTSourceWrapper : public clang::ExternalSemaSource {
22181344Sdfr  ExternalASTSource *m_Source;
23181344Sdfr
24181344Sdfrpublic:
25181344Sdfr  ExternalASTSourceWrapper(ExternalASTSource *Source) : m_Source(Source) {
26181344Sdfr    assert(m_Source && "Can't wrap nullptr ExternalASTSource");
27203026Sgavin  }
28181344Sdfr
29181344Sdfr  ~ExternalASTSourceWrapper() override;
30181344Sdfr
31181344Sdfr  clang::Decl *GetExternalDecl(uint32_t ID) override {
32181344Sdfr    return m_Source->GetExternalDecl(ID);
33181344Sdfr  }
34181344Sdfr
35181344Sdfr  clang::Selector GetExternalSelector(uint32_t ID) override {
36181344Sdfr    return m_Source->GetExternalSelector(ID);
37181344Sdfr  }
38181344Sdfr
39181344Sdfr  uint32_t GetNumExternalSelectors() override {
40181344Sdfr    return m_Source->GetNumExternalSelectors();
41181344Sdfr  }
42181344Sdfr
43181344Sdfr  clang::Stmt *GetExternalDeclStmt(uint64_t Offset) override {
44181344Sdfr    return m_Source->GetExternalDeclStmt(Offset);
45181344Sdfr  }
46181344Sdfr
47181344Sdfr  clang::CXXCtorInitializer **
48181344Sdfr  GetExternalCXXCtorInitializers(uint64_t Offset) override {
49181344Sdfr    return m_Source->GetExternalCXXCtorInitializers(Offset);
50181344Sdfr  }
51181344Sdfr
52181344Sdfr  clang::CXXBaseSpecifier *
53181344Sdfr  GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
54181344Sdfr    return m_Source->GetExternalCXXBaseSpecifiers(Offset);
55181344Sdfr  }
56181344Sdfr
57181344Sdfr  void updateOutOfDateIdentifier(clang::IdentifierInfo &II) override {
58181344Sdfr    m_Source->updateOutOfDateIdentifier(II);
59181344Sdfr  }
60181344Sdfr
61181344Sdfr  bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
62181344Sdfr                                      clang::DeclarationName Name) override {
63203025Sgavin    return m_Source->FindExternalVisibleDeclsByName(DC, Name);
64181344Sdfr  }
65181344Sdfr
66181344Sdfr  void completeVisibleDeclsMap(const clang::DeclContext *DC) override {
67181344Sdfr    m_Source->completeVisibleDeclsMap(DC);
68181344Sdfr  }
69
70  clang::Module *getModule(unsigned ID) override {
71    return m_Source->getModule(ID);
72  }
73
74  llvm::Optional<ASTSourceDescriptor>
75  getSourceDescriptor(unsigned ID) override {
76    return m_Source->getSourceDescriptor(ID);
77  }
78
79  ExtKind hasExternalDefinitions(const clang::Decl *D) override {
80    return m_Source->hasExternalDefinitions(D);
81  }
82
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);
88  }
89
90  void
91  FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length,
92                      llvm::SmallVectorImpl<clang::Decl *> &Decls) override {
93    m_Source->FindFileRegionDecls(File, Offset, Length, Decls);
94  }
95
96  void CompleteRedeclChain(const clang::Decl *D) override {
97    m_Source->CompleteRedeclChain(D);
98  }
99
100  void CompleteType(clang::TagDecl *Tag) override {
101    m_Source->CompleteType(Tag);
102  }
103
104  void CompleteType(clang::ObjCInterfaceDecl *Class) override {
105    m_Source->CompleteType(Class);
106  }
107
108  void ReadComments() override { m_Source->ReadComments(); }
109
110  void StartedDeserializing() override { m_Source->StartedDeserializing(); }
111
112  void FinishedDeserializing() override { m_Source->FinishedDeserializing(); }
113
114  void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
115    m_Source->StartTranslationUnit(Consumer);
116  }
117
118  void PrintStats() override;
119
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>
124          &BaseOffsets,
125      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
126          &VirtualBaseOffsets) override {
127    return m_Source->layoutRecordType(Record, Size, Alignment, FieldOffsets,
128                                      BaseOffsets, VirtualBaseOffsets);
129  }
130};
131
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.
135class ASTConsumerForwarder : public clang::SemaConsumer {
136  clang::ASTConsumer *m_c;
137  clang::SemaConsumer *m_sc;
138
139public:
140  ASTConsumerForwarder(clang::ASTConsumer *c) : m_c(c) {
141    m_sc = llvm::dyn_cast<clang::SemaConsumer>(m_c);
142  }
143
144  ~ASTConsumerForwarder() override;
145
146  void Initialize(clang::ASTContext &Context) override {
147    m_c->Initialize(Context);
148  }
149
150  bool HandleTopLevelDecl(clang::DeclGroupRef D) override {
151    return m_c->HandleTopLevelDecl(D);
152  }
153
154  void HandleInlineFunctionDefinition(clang::FunctionDecl *D) override {
155    m_c->HandleInlineFunctionDefinition(D);
156  }
157
158  void HandleInterestingDecl(clang::DeclGroupRef D) override {
159    m_c->HandleInterestingDecl(D);
160  }
161
162  void HandleTranslationUnit(clang::ASTContext &Ctx) override {
163    m_c->HandleTranslationUnit(Ctx);
164  }
165
166  void HandleTagDeclDefinition(clang::TagDecl *D) override {
167    m_c->HandleTagDeclDefinition(D);
168  }
169
170  void HandleTagDeclRequiredDefinition(const clang::TagDecl *D) override {
171    m_c->HandleTagDeclRequiredDefinition(D);
172  }
173
174  void HandleCXXImplicitFunctionInstantiation(clang::FunctionDecl *D) override {
175    m_c->HandleCXXImplicitFunctionInstantiation(D);
176  }
177
178  void HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef D) override {
179    m_c->HandleTopLevelDeclInObjCContainer(D);
180  }
181
182  void HandleImplicitImportDecl(clang::ImportDecl *D) override {
183    m_c->HandleImplicitImportDecl(D);
184  }
185
186  void CompleteTentativeDefinition(clang::VarDecl *D) override {
187    m_c->CompleteTentativeDefinition(D);
188  }
189
190  void AssignInheritanceModel(clang::CXXRecordDecl *RD) override {
191    m_c->AssignInheritanceModel(RD);
192  }
193
194  void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *D) override {
195    m_c->HandleCXXStaticMemberVarInstantiation(D);
196  }
197
198  void HandleVTable(clang::CXXRecordDecl *RD) override {
199    m_c->HandleVTable(RD);
200  }
201
202  clang::ASTMutationListener *GetASTMutationListener() override {
203    return m_c->GetASTMutationListener();
204  }
205
206  clang::ASTDeserializationListener *GetASTDeserializationListener() override {
207    return m_c->GetASTDeserializationListener();
208  }
209
210  void PrintStats() override;
211
212  void InitializeSema(clang::Sema &S) override {
213    if (m_sc)
214      m_sc->InitializeSema(S);
215  }
216
217  /// Inform the semantic consumer that Sema is no longer available.
218  void ForgetSema() override {
219    if (m_sc)
220      m_sc->ForgetSema();
221  }
222
223  bool shouldSkipFunctionBody(clang::Decl *D) override {
224    return m_c->shouldSkipFunctionBody(D);
225  }
226};
227
228/// A ExternalSemaSource multiplexer that prioritizes its sources.
229///
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.
235///
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.
241class SemaSourceWithPriorities : public clang::ExternalSemaSource {
242
243private:
244  /// The sources ordered in decreasing priority.
245  llvm::SmallVector<clang::ExternalSemaSource *, 2> Sources;
246
247public:
248  /// Construct a SemaSourceWithPriorities with a 'high quality' source that
249  /// has the higher priority and a 'low quality' source that will be used
250  /// as a fallback.
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);
255  }
256
257  ~SemaSourceWithPriorities() override;
258
259  void addSource(clang::ExternalSemaSource &source) {
260    Sources.push_back(&source);
261  }
262
263  //===--------------------------------------------------------------------===//
264  // ExternalASTSource.
265  //===--------------------------------------------------------------------===//
266
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))
270        return Result;
271    return nullptr;
272  }
273
274  void CompleteRedeclChain(const clang::Decl *D) override {
275    for (size_t i = 0; i < Sources.size(); ++i)
276      Sources[i]->CompleteRedeclChain(D);
277  }
278
279  clang::Selector GetExternalSelector(uint32_t ID) override {
280    clang::Selector Sel;
281    for (size_t i = 0; i < Sources.size(); ++i) {
282      Sel = Sources[i]->GetExternalSelector(ID);
283      if (!Sel.isNull())
284        return Sel;
285    }
286    return Sel;
287  }
288
289  uint32_t GetNumExternalSelectors() override {
290    for (size_t i = 0; i < Sources.size(); ++i)
291      if (uint32_t total = Sources[i]->GetNumExternalSelectors())
292        return total;
293    return 0;
294  }
295
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))
299        return Result;
300    return nullptr;
301  }
302
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))
308        return R;
309    return nullptr;
310  }
311
312  clang::CXXCtorInitializer **
313  GetExternalCXXCtorInitializers(uint64_t Offset) override {
314    for (auto *S : Sources)
315      if (auto *R = S->GetExternalCXXCtorInitializers(Offset))
316        return R;
317    return nullptr;
318  }
319
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)
324          return EK;
325    return EK_ReplyHazy;
326  }
327
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))
332        return true;
333    return false;
334  }
335
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);
340  }
341
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);
348      if (!Result.empty())
349        return;
350    }
351  }
352
353  void
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);
358  }
359
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())
368          break;
369      }
370  }
371
372  void CompleteType(clang::ObjCInterfaceDecl *Class) override {
373    for (size_t i = 0; i < Sources.size(); ++i)
374      Sources[i]->CompleteType(Class);
375  }
376
377  void ReadComments() override {
378    for (size_t i = 0; i < Sources.size(); ++i)
379      Sources[i]->ReadComments();
380  }
381
382  void StartedDeserializing() override {
383    for (size_t i = 0; i < Sources.size(); ++i)
384      Sources[i]->StartedDeserializing();
385  }
386
387  void FinishedDeserializing() override {
388    for (size_t i = 0; i < Sources.size(); ++i)
389      Sources[i]->FinishedDeserializing();
390  }
391
392  void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
393    for (size_t i = 0; i < Sources.size(); ++i)
394      Sources[i]->StartTranslationUnit(Consumer);
395  }
396
397  void PrintStats() override;
398
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))
402        return M;
403    return nullptr;
404  }
405
406  bool DeclIsFromPCHWithObjectFile(const clang::Decl *D) override {
407    for (auto *S : Sources)
408      if (S->DeclIsFromPCHWithObjectFile(D))
409        return true;
410    return false;
411  }
412
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>
417          &BaseOffsets,
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))
423        return true;
424    return false;
425  }
426
427  void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override {
428    for (auto &Source : Sources)
429      Source->getMemoryBufferSizes(sizes);
430  }
431
432  //===--------------------------------------------------------------------===//
433  // ExternalSemaSource.
434  //===--------------------------------------------------------------------===//
435
436  void InitializeSema(clang::Sema &S) override {
437    for (auto &Source : Sources)
438      Source->InitializeSema(S);
439  }
440
441  void ForgetSema() override {
442    for (auto &Source : Sources)
443      Source->ForgetSema();
444  }
445
446  void ReadMethodPool(clang::Selector Sel) override {
447    for (auto &Source : Sources)
448      Source->ReadMethodPool(Sel);
449  }
450
451  void updateOutOfDateSelector(clang::Selector Sel) override {
452    for (auto &Source : Sources)
453      Source->updateOutOfDateSelector(Sel);
454  }
455
456  void ReadKnownNamespaces(
457      llvm::SmallVectorImpl<clang::NamespaceDecl *> &Namespaces) override {
458    for (auto &Source : Sources)
459      Source->ReadKnownNamespaces(Namespaces);
460  }
461
462  void ReadUndefinedButUsed(
463      llvm::MapVector<clang::NamedDecl *, clang::SourceLocation> &Undefined)
464      override {
465    for (auto &Source : Sources)
466      Source->ReadUndefinedButUsed(Undefined);
467  }
468
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);
475  }
476
477  bool LookupUnqualified(clang::LookupResult &R, clang::Scope *S) override {
478    for (auto &Source : Sources) {
479      Source->LookupUnqualified(R, S);
480      if (!R.empty())
481        break;
482    }
483
484    return !R.empty();
485  }
486
487  void ReadTentativeDefinitions(
488      llvm::SmallVectorImpl<clang::VarDecl *> &Defs) override {
489    for (auto &Source : Sources)
490      Source->ReadTentativeDefinitions(Defs);
491  }
492
493  void ReadUnusedFileScopedDecls(
494      llvm::SmallVectorImpl<const clang::DeclaratorDecl *> &Decls) override {
495    for (auto &Source : Sources)
496      Source->ReadUnusedFileScopedDecls(Decls);
497  }
498
499  void ReadDelegatingConstructors(
500      llvm::SmallVectorImpl<clang::CXXConstructorDecl *> &Decls) override {
501    for (auto &Source : Sources)
502      Source->ReadDelegatingConstructors(Decls);
503  }
504
505  void ReadExtVectorDecls(
506      llvm::SmallVectorImpl<clang::TypedefNameDecl *> &Decls) override {
507    for (auto &Source : Sources)
508      Source->ReadExtVectorDecls(Decls);
509  }
510
511  void ReadUnusedLocalTypedefNameCandidates(
512      llvm::SmallSetVector<const clang::TypedefNameDecl *, 4> &Decls) override {
513    for (auto &Source : Sources)
514      Source->ReadUnusedLocalTypedefNameCandidates(Decls);
515  }
516
517  void ReadReferencedSelectors(
518      llvm::SmallVectorImpl<std::pair<clang::Selector, clang::SourceLocation>>
519          &Sels) override {
520    for (auto &Source : Sources)
521      Source->ReadReferencedSelectors(Sels);
522  }
523
524  void ReadWeakUndeclaredIdentifiers(
525      llvm::SmallVectorImpl<std::pair<clang::IdentifierInfo *, clang::WeakInfo>>
526          &WI) override {
527    for (auto &Source : Sources)
528      Source->ReadWeakUndeclaredIdentifiers(WI);
529  }
530
531  void ReadUsedVTables(
532      llvm::SmallVectorImpl<clang::ExternalVTableUse> &VTables) override {
533    for (auto &Source : Sources)
534      Source->ReadUsedVTables(VTables);
535  }
536
537  void ReadPendingInstantiations(
538      llvm::SmallVectorImpl<
539          std::pair<clang::ValueDecl *, clang::SourceLocation>> &Pending)
540      override {
541    for (auto &Source : Sources)
542      Source->ReadPendingInstantiations(Pending);
543  }
544
545  void ReadLateParsedTemplates(
546      llvm::MapVector<const clang::FunctionDecl *,
547                      std::unique_ptr<clang::LateParsedTemplate>> &LPTMap)
548      override {
549    for (auto &Source : Sources)
550      Source->ReadLateParsedTemplates(LPTMap);
551  }
552
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))
563        return C;
564    }
565    return clang::TypoCorrection();
566  }
567
568  bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc,
569                                        clang::QualType T) override {
570    for (auto &Source : Sources) {
571      if (Source->MaybeDiagnoseMissingCompleteType(Loc, T))
572        return true;
573    }
574    return false;
575  }
576};
577
578} // namespace lldb_private
579#endif // liblldb_ASTUtils_h_
580