ExternalASTMerger.h 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file declares the ExternalASTMerger, which vends a combination of ASTs
  15. // from several different ASTContext/FileManager pairs
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
  19. #define LLVM_CLANG_AST_EXTERNALASTMERGER_H
  20. #include "clang/AST/ASTImporter.h"
  21. #include "clang/AST/ASTImporterSharedState.h"
  22. #include "clang/AST/ExternalASTSource.h"
  23. #include "llvm/Support/raw_ostream.h"
  24. namespace clang {
  25. /// ExternalASTSource implementation that merges information from several
  26. /// ASTContexts.
  27. ///
  28. /// ExternalASTMerger maintains a vector of ASTImporters that it uses to import
  29. /// (potentially incomplete) Decls and DeclContexts from the source ASTContexts
  30. /// in response to ExternalASTSource API calls.
  31. ///
  32. /// When lookup occurs in the resulting imported DeclContexts, the original
  33. /// DeclContexts need to be queried. Roughly, there are three cases here:
  34. ///
  35. /// - The DeclContext of origin can be found by simple name lookup. In this
  36. /// case, no additional state is required.
  37. ///
  38. /// - The DeclContext of origin is different from what would be found by name
  39. /// lookup. In this case, Origins contains an entry overriding lookup and
  40. /// specifying the correct pair of DeclContext/ASTContext.
  41. ///
  42. /// - The DeclContext of origin was determined by another ExternalASTMerger.
  43. /// (This is possible when the source ASTContext for one of the Importers has
  44. /// its own ExternalASTMerger). The origin must be properly forwarded in this
  45. /// case.
  46. ///
  47. /// ExternalASTMerger's job is to maintain the data structures necessary to
  48. /// allow this. The data structures themselves can be extracted (read-only) and
  49. /// copied for re-use.
  50. class ExternalASTMerger : public ExternalASTSource {
  51. public:
  52. /// A single origin for a DeclContext. Unlike Decls, DeclContexts do
  53. /// not allow their containing ASTContext to be determined in all cases.
  54. struct DCOrigin {
  55. DeclContext *DC;
  56. ASTContext *AST;
  57. };
  58. typedef std::map<const DeclContext *, DCOrigin> OriginMap;
  59. typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector;
  60. private:
  61. /// One importer exists for each source.
  62. ImporterVector Importers;
  63. /// Overrides in case name lookup would return nothing or would return
  64. /// the wrong thing.
  65. OriginMap Origins;
  66. /// The installed log stream.
  67. llvm::raw_ostream *LogStream;
  68. public:
  69. /// The target for an ExternalASTMerger.
  70. ///
  71. /// ASTImporters require both ASTContext and FileManager to be able to
  72. /// import SourceLocations properly.
  73. struct ImporterTarget {
  74. ASTContext &AST;
  75. FileManager &FM;
  76. };
  77. /// A source for an ExternalASTMerger.
  78. ///
  79. /// ASTImporters require both ASTContext and FileManager to be able to
  80. /// import SourceLocations properly. Additionally, when import occurs for
  81. /// a DeclContext whose origin has been overridden, then this
  82. /// ExternalASTMerger must be able to determine that.
  83. class ImporterSource {
  84. ASTContext &AST;
  85. FileManager &FM;
  86. const OriginMap &OM;
  87. /// True iff the source only exists temporary, i.e., it will be removed from
  88. /// the ExternalASTMerger during the life time of the ExternalASTMerger.
  89. bool Temporary;
  90. /// If the ASTContext of this source has an ExternalASTMerger that imports
  91. /// into this source, then this will point to that other ExternalASTMerger.
  92. ExternalASTMerger *Merger;
  93. public:
  94. ImporterSource(ASTContext &AST, FileManager &FM, const OriginMap &OM,
  95. bool Temporary = false, ExternalASTMerger *Merger = nullptr)
  96. : AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {}
  97. ASTContext &getASTContext() const { return AST; }
  98. FileManager &getFileManager() const { return FM; }
  99. const OriginMap &getOriginMap() const { return OM; }
  100. bool isTemporary() const { return Temporary; }
  101. ExternalASTMerger *getMerger() const { return Merger; }
  102. };
  103. private:
  104. /// The target for this ExternalASTMerger.
  105. ImporterTarget Target;
  106. /// ExternalASTMerger has multiple ASTImporters that import into the same
  107. /// TU. This is the shared state for all ASTImporters of this
  108. /// ExternalASTMerger.
  109. /// See also the CrossTranslationUnitContext that has a similar setup.
  110. std::shared_ptr<ASTImporterSharedState> SharedState;
  111. public:
  112. ExternalASTMerger(const ImporterTarget &Target,
  113. llvm::ArrayRef<ImporterSource> Sources);
  114. /// Asks all connected ASTImporters if any of them imported the given
  115. /// declaration. If any ASTImporter did import the given declaration,
  116. /// then this function returns the declaration that D was imported from.
  117. /// Returns nullptr if no ASTImporter did import import D.
  118. Decl *FindOriginalDecl(Decl *D);
  119. /// Add a set of ASTContexts as possible origins.
  120. ///
  121. /// Usually the set will be initialized in the constructor, but long-lived
  122. /// ExternalASTMergers may need to import from new sources (for example,
  123. /// newly-parsed source files).
  124. ///
  125. /// Ensures that Importers does not gain duplicate entries as a result.
  126. void AddSources(llvm::ArrayRef<ImporterSource> Sources);
  127. /// Remove a set of ASTContexts as possible origins.
  128. ///
  129. /// Sometimes an origin goes away (for example, if a source file gets
  130. /// superseded by a newer version).
  131. ///
  132. /// The caller is responsible for ensuring that this doesn't leave
  133. /// DeclContexts that can't be completed.
  134. void RemoveSources(llvm::ArrayRef<ImporterSource> Sources);
  135. /// Implementation of the ExternalASTSource API.
  136. bool FindExternalVisibleDeclsByName(const DeclContext *DC,
  137. DeclarationName Name) override;
  138. /// Implementation of the ExternalASTSource API.
  139. void
  140. FindExternalLexicalDecls(const DeclContext *DC,
  141. llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
  142. SmallVectorImpl<Decl *> &Result) override;
  143. /// Implementation of the ExternalASTSource API.
  144. void CompleteType(TagDecl *Tag) override;
  145. /// Implementation of the ExternalASTSource API.
  146. void CompleteType(ObjCInterfaceDecl *Interface) override;
  147. /// Returns true if DC can be found in any source AST context.
  148. bool CanComplete(DeclContext *DC);
  149. /// Records an origin in Origins only if name lookup would find
  150. /// something different or nothing at all.
  151. void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
  152. /// Regardless of any checks, override the Origin for a DeclContext.
  153. void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
  154. /// Get a read-only view of the Origins map, for use in constructing
  155. /// an ImporterSource for another ExternalASTMerger.
  156. const OriginMap &GetOrigins() { return Origins; }
  157. /// Returns true if Importers contains an ASTImporter whose source is
  158. /// OriginContext.
  159. bool HasImporterForOrigin(ASTContext &OriginContext);
  160. /// Returns a reference to the ASTImporter from Importers whose origin
  161. /// is OriginContext. This allows manual import of ASTs while preserving the
  162. /// OriginMap correctly.
  163. ASTImporter &ImporterForOrigin(ASTContext &OriginContext);
  164. /// Sets the current log stream.
  165. void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
  166. private:
  167. /// Records and origin in Origins.
  168. void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
  169. ASTImporter &importer);
  170. /// Performs an action for every DeclContext that is identified as
  171. /// corresponding (either by forced origin or by name lookup) to DC.
  172. template <typename CallbackType>
  173. void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback);
  174. public:
  175. /// Log something if there is a logging callback installed.
  176. llvm::raw_ostream &logs() { return *LogStream; }
  177. /// True if the log stream is not llvm::nulls();
  178. bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
  179. };
  180. } // end namespace clang
  181. #endif
  182. #ifdef __GNUC__
  183. #pragma GCC diagnostic pop
  184. #endif