1 //===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file declares the ExternalASTMerger, which vends a combination of ASTs
11 // from several different ASTContext/FileManager pairs
13 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
15 #define LLVM_CLANG_AST_EXTERNALASTMERGER_H
17 #include "clang/AST/ASTImporter.h"
18 #include "clang/AST/ExternalASTSource.h"
19 #include "llvm/Support/raw_ostream.h"
23 /// ExternalASTSource implementation that merges information from several
26 /// ExtermalASTMerger 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.
30 /// When lookup occurs in the resulting imported DeclContexts, the original
31 /// DeclContexts need to be queried. Roughly, there are three cases here:
33 /// - The DeclContext of origin can be found by simple name lookup. In this
34 /// case, no additional state is required.
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.
40 /// - The DeclContext of origin was determined by another ExterenalASTMerger.
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
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 {
50 /// A single origin for a DeclContext. Unlike Decls, DeclContexts do
51 /// not allow their containing ASTContext to be determined in all cases.
57 typedef std::map<const DeclContext *, DCOrigin> OriginMap;
58 typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector;
60 /// One importer exists for each source.
61 ImporterVector Importers;
62 /// Overrides in case name lookup would return nothing or would return
65 /// The installed log stream.
66 llvm::raw_ostream *LogStream;
69 /// The target for an ExternalASTMerger.
71 /// ASTImporters require both ASTContext and FileManager to be able to
72 /// import SourceLocations properly.
73 struct ImporterTarget {
77 /// A source for an ExternalASTMerger.
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 struct ImporterSource {
90 /// The target for this ExtenralASTMerger.
91 ImporterTarget Target;
94 ExternalASTMerger(const ImporterTarget &Target,
95 llvm::ArrayRef<ImporterSource> Sources);
97 /// Add a set of ASTContexts as possible origins.
99 /// Usually the set will be initialized in the constructor, but long-lived
100 /// ExternalASTMergers may neeed to import from new sources (for example,
101 /// newly-parsed source files).
103 /// Ensures that Importers does not gain duplicate entries as a result.
104 void AddSources(llvm::ArrayRef<ImporterSource> Sources);
106 /// Remove a set of ASTContexts as possible origins.
108 /// Sometimes an origin goes away (for example, if a source file gets
109 /// superseded by a newer version).
111 /// The caller is responsible for ensuring that this doesn't leave
112 /// DeclContexts that can't be completed.
113 void RemoveSources(llvm::ArrayRef<ImporterSource> Sources);
115 /// Implementation of the ExternalASTSource API.
116 bool FindExternalVisibleDeclsByName(const DeclContext *DC,
117 DeclarationName Name) override;
119 /// Implementation of the ExternalASTSource API.
121 FindExternalLexicalDecls(const DeclContext *DC,
122 llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
123 SmallVectorImpl<Decl *> &Result) override;
125 /// Implementation of the ExternalASTSource API.
126 void CompleteType(TagDecl *Tag) override;
128 /// Implementation of the ExternalASTSource API.
129 void CompleteType(ObjCInterfaceDecl *Interface) override;
131 /// Returns true if DC can be found in any source AST context.
132 bool CanComplete(DeclContext *DC);
134 /// Records an origin in Origins only if name lookup would find
135 /// something different or nothing at all.
136 void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
138 /// Regardless of any checks, override the Origin for a DeclContext.
139 void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
141 /// Get a read-only view of the Origins map, for use in constructing
142 /// an ImporterSource for another ExternalASTMerger.
143 const OriginMap &GetOrigins() { return Origins; }
145 /// Returns true if Importers contains an ASTImporter whose source is
147 bool HasImporterForOrigin(ASTContext &OriginContext);
149 /// Returns a reference to the ASTRImporter from Importers whose origin
150 /// is OriginContext. This allows manual import of ASTs while preserving the
151 /// OriginMap correctly.
152 ASTImporter &ImporterForOrigin(ASTContext &OriginContext);
154 /// Sets the current log stream.
155 void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
157 /// Records and origin in Origins.
158 void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
159 ASTImporter &importer);
161 /// Performs an action for every DeclContext that is identified as
162 /// corresponding (either by forced origin or by name lookup) to DC.
163 template <typename CallbackType>
164 void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback);
167 /// Log something if there is a logging callback installed.
168 llvm::raw_ostream &logs() { return *LogStream; }
170 /// True if the log stream is not llvm::nulls();
171 bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
174 } // end namespace clang