/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/ExternalASTMerger.h
Line | Count | Source (jump to first uncovered line) |
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 | 198 | : AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {} |
98 | 564 | ASTContext &getASTContext() const { return AST; } |
99 | 264 | FileManager &getFileManager() const { return FM; } |
100 | 132 | const OriginMap &getOriginMap() const { return OM; } |
101 | 132 | bool isTemporary() const { return Temporary; } |
102 | 264 | 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 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 | 129 | 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 | 0 | 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 | 0 | llvm::raw_ostream &logs() { return *LogStream; } |
196 | | |
197 | | /// True if the log stream is not llvm::nulls(); |
198 | 1.52k | bool LoggingEnabled() { return LogStream != &llvm::nulls(); } |
199 | | }; |
200 | | |
201 | | } // end namespace clang |
202 | | |
203 | | #endif |