Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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/ASTImporterSharedState.h" |
||
18 | #include "clang/AST/ExternalASTSource.h" |
||
19 | #include "llvm/Support/raw_ostream.h" |
||
20 | |||
21 | namespace clang { |
||
22 | |||
23 | /// ExternalASTSource implementation that merges information from several |
||
24 | /// ASTContexts. |
||
25 | /// |
||
26 | /// ExternalASTMerger maintains a vector of ASTImporters that it uses to import |
||
27 | /// (potentially incomplete) Decls and DeclContexts from the source ASTContexts |
||
28 | /// in response to ExternalASTSource API calls. |
||
29 | /// |
||
30 | /// When lookup occurs in the resulting imported DeclContexts, the original |
||
31 | /// DeclContexts need to be queried. Roughly, there are three cases here: |
||
32 | /// |
||
33 | /// - The DeclContext of origin can be found by simple name lookup. In this |
||
34 | /// case, no additional state is required. |
||
35 | /// |
||
36 | /// - The DeclContext of origin is different from what would be found by name |
||
37 | /// lookup. In this case, Origins contains an entry overriding lookup and |
||
38 | /// specifying the correct pair of DeclContext/ASTContext. |
||
39 | /// |
||
40 | /// - The DeclContext of origin was determined by another ExternalASTMerger. |
||
41 | /// (This is possible when the source ASTContext for one of the Importers has |
||
42 | /// its own ExternalASTMerger). The origin must be properly forwarded in this |
||
43 | /// case. |
||
44 | /// |
||
45 | /// ExternalASTMerger's job is to maintain the data structures necessary to |
||
46 | /// allow this. The data structures themselves can be extracted (read-only) and |
||
47 | /// copied for re-use. |
||
48 | class ExternalASTMerger : public ExternalASTSource { |
||
49 | public: |
||
50 | /// A single origin for a DeclContext. Unlike Decls, DeclContexts do |
||
51 | /// not allow their containing ASTContext to be determined in all cases. |
||
52 | struct DCOrigin { |
||
53 | DeclContext *DC; |
||
54 | ASTContext *AST; |
||
55 | }; |
||
56 | |||
57 | typedef std::map<const DeclContext *, DCOrigin> OriginMap; |
||
58 | typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector; |
||
59 | private: |
||
60 | /// One importer exists for each source. |
||
61 | ImporterVector Importers; |
||
62 | /// Overrides in case name lookup would return nothing or would return |
||
63 | /// the wrong thing. |
||
64 | OriginMap Origins; |
||
65 | /// The installed log stream. |
||
66 | llvm::raw_ostream *LogStream; |
||
67 | |||
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 | |||
94 | public: |
||
95 | ImporterSource(ASTContext &AST, FileManager &FM, const OriginMap &OM, |
||
96 | bool Temporary = false, ExternalASTMerger *Merger = nullptr) |
||
97 | : AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {} |
||
98 | ASTContext &getASTContext() const { return AST; } |
||
99 | FileManager &getFileManager() const { return FM; } |
||
100 | const OriginMap &getOriginMap() const { return OM; } |
||
101 | bool isTemporary() const { return Temporary; } |
||
102 | ExternalASTMerger *getMerger() const { return Merger; } |
||
103 | }; |
||
104 | |||
105 | private: |
||
106 | /// The target for this ExternalASTMerger. |
||
107 | ImporterTarget Target; |
||
108 | /// ExternalASTMerger has multiple ASTImporters that import into the same |
||
109 | /// TU. This is the shared state for all ASTImporters of this |
||
110 | /// ExternalASTMerger. |
||
111 | /// See also the CrossTranslationUnitContext that has a similar setup. |
||
112 | std::shared_ptr<ASTImporterSharedState> SharedState; |
||
113 | |||
114 | public: |
||
115 | ExternalASTMerger(const ImporterTarget &Target, |
||
116 | llvm::ArrayRef<ImporterSource> Sources); |
||
117 | |||
118 | /// Asks all connected ASTImporters if any of them imported the given |
||
119 | /// declaration. If any ASTImporter did import the given declaration, |
||
120 | /// then this function returns the declaration that D was imported from. |
||
121 | /// Returns nullptr if no ASTImporter did import D. |
||
122 | Decl *FindOriginalDecl(Decl *D); |
||
123 | |||
124 | /// Add a set of ASTContexts as possible origins. |
||
125 | /// |
||
126 | /// Usually the set will be initialized in the constructor, but long-lived |
||
127 | /// ExternalASTMergers may need to import from new sources (for example, |
||
128 | /// newly-parsed source files). |
||
129 | /// |
||
130 | /// Ensures that Importers does not gain duplicate entries as a result. |
||
131 | void AddSources(llvm::ArrayRef<ImporterSource> Sources); |
||
132 | |||
133 | /// Remove a set of ASTContexts as possible origins. |
||
134 | /// |
||
135 | /// Sometimes an origin goes away (for example, if a source file gets |
||
136 | /// superseded by a newer version). |
||
137 | /// |
||
138 | /// The caller is responsible for ensuring that this doesn't leave |
||
139 | /// DeclContexts that can't be completed. |
||
140 | void RemoveSources(llvm::ArrayRef<ImporterSource> Sources); |
||
141 | |||
142 | /// Implementation of the ExternalASTSource API. |
||
143 | bool FindExternalVisibleDeclsByName(const DeclContext *DC, |
||
144 | DeclarationName Name) override; |
||
145 | |||
146 | /// Implementation of the ExternalASTSource API. |
||
147 | void |
||
148 | FindExternalLexicalDecls(const DeclContext *DC, |
||
149 | llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, |
||
150 | SmallVectorImpl<Decl *> &Result) override; |
||
151 | |||
152 | /// Implementation of the ExternalASTSource API. |
||
153 | void CompleteType(TagDecl *Tag) override; |
||
154 | |||
155 | /// Implementation of the ExternalASTSource API. |
||
156 | void CompleteType(ObjCInterfaceDecl *Interface) override; |
||
157 | |||
158 | /// Returns true if DC can be found in any source AST context. |
||
159 | bool CanComplete(DeclContext *DC); |
||
160 | |||
161 | /// Records an origin in Origins only if name lookup would find |
||
162 | /// something different or nothing at all. |
||
163 | void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin); |
||
164 | |||
165 | /// Regardless of any checks, override the Origin for a DeclContext. |
||
166 | void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin); |
||
167 | |||
168 | /// Get a read-only view of the Origins map, for use in constructing |
||
169 | /// an ImporterSource for another ExternalASTMerger. |
||
170 | const OriginMap &GetOrigins() { return Origins; } |
||
171 | |||
172 | /// Returns true if Importers contains an ASTImporter whose source is |
||
173 | /// OriginContext. |
||
174 | bool HasImporterForOrigin(ASTContext &OriginContext); |
||
175 | |||
176 | /// Returns a reference to the ASTImporter from Importers whose origin |
||
177 | /// is OriginContext. This allows manual import of ASTs while preserving the |
||
178 | /// OriginMap correctly. |
||
179 | ASTImporter &ImporterForOrigin(ASTContext &OriginContext); |
||
180 | |||
181 | /// Sets the current log stream. |
||
182 | void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; } |
||
183 | private: |
||
184 | /// Records and origin in Origins. |
||
185 | void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, |
||
186 | ASTImporter &importer); |
||
187 | |||
188 | /// Performs an action for every DeclContext that is identified as |
||
189 | /// corresponding (either by forced origin or by name lookup) to DC. |
||
190 | template <typename CallbackType> |
||
191 | void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback); |
||
192 | |||
193 | public: |
||
194 | /// Log something if there is a logging callback installed. |
||
195 | llvm::raw_ostream &logs() { return *LogStream; } |
||
196 | |||
197 | /// True if the log stream is not llvm::nulls(); |
||
198 | bool LoggingEnabled() { return LogStream != &llvm::nulls(); } |
||
199 | }; |
||
200 | |||
201 | } // end namespace clang |
||
202 | |||
203 | #endif |