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