1 //===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file declares the ExternalASTMerger, which vends a combination of ASTs
10 // from several different ASTContext/FileManager pairs
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
14 #define LLVM_CLANG_AST_EXTERNALASTMERGER_H
16 #include "clang/AST/ASTImporter.h"
17 #include "clang/AST/ExternalASTSource.h"
18 #include "llvm/Support/raw_ostream.h"
22 /// ExternalASTSource implementation that merges information from several
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.
29 /// When lookup occurs in the resulting imported DeclContexts, the original
30 /// DeclContexts need to be queried. Roughly, there are three cases here:
32 /// - The DeclContext of origin can be found by simple name lookup. In this
33 /// case, no additional state is required.
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.
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
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 {
49 /// A single origin for a DeclContext. Unlike Decls, DeclContexts do
50 /// not allow their containing ASTContext to be determined in all cases.
56 typedef std::map<const DeclContext *, DCOrigin> OriginMap;
57 typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector;
59 /// One importer exists for each source.
60 ImporterVector Importers;
61 /// Overrides in case name lookup would return nothing or would return
64 /// The installed log stream.
65 llvm::raw_ostream *LogStream;
68 /// The target for an ExternalASTMerger.
70 /// ASTImporters require both ASTContext and FileManager to be able to
71 /// import SourceLocations properly.
72 struct ImporterTarget {
76 /// A source for an ExternalASTMerger.
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 {
89 /// The target for this ExtenralASTMerger.
90 ImporterTarget Target;
93 ExternalASTMerger(const ImporterTarget &Target,
94 llvm::ArrayRef<ImporterSource> Sources);
96 /// Add a set of ASTContexts as possible origins.
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).
102 /// Ensures that Importers does not gain duplicate entries as a result.
103 void AddSources(llvm::ArrayRef<ImporterSource> Sources);
105 /// Remove a set of ASTContexts as possible origins.
107 /// Sometimes an origin goes away (for example, if a source file gets
108 /// superseded by a newer version).
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);
114 /// Implementation of the ExternalASTSource API.
115 bool FindExternalVisibleDeclsByName(const DeclContext *DC,
116 DeclarationName Name) override;
118 /// Implementation of the ExternalASTSource API.
120 FindExternalLexicalDecls(const DeclContext *DC,
121 llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
122 SmallVectorImpl<Decl *> &Result) override;
124 /// Implementation of the ExternalASTSource API.
125 void CompleteType(TagDecl *Tag) override;
127 /// Implementation of the ExternalASTSource API.
128 void CompleteType(ObjCInterfaceDecl *Interface) override;
130 /// Returns true if DC can be found in any source AST context.
131 bool CanComplete(DeclContext *DC);
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);
137 /// Regardless of any checks, override the Origin for a DeclContext.
138 void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
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; }
144 /// Returns true if Importers contains an ASTImporter whose source is
146 bool HasImporterForOrigin(ASTContext &OriginContext);
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);
153 /// Sets the current log stream.
154 void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
156 /// Records and origin in Origins.
157 void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
158 ASTImporter &importer);
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);
166 /// Log something if there is a logging callback installed.
167 llvm::raw_ostream &logs() { return *LogStream; }
169 /// True if the log stream is not llvm::nulls();
170 bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
173 } // end namespace clang