1//===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file declares the ExternalASTMerger, which vends a combination of ASTs
11//  from several different ASTContext/FileManager pairs
12//
13//===----------------------------------------------------------------------===//
14#ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
15#define LLVM_CLANG_AST_EXTERNALASTMERGER_H
16
17#include "clang/AST/ASTImporter.h"
18#include "clang/AST/ExternalASTSource.h"
19#include "llvm/Support/raw_ostream.h"
20
21namespace clang {
22
23/// ExternalASTSource implementation that merges information from several
24/// ASTContexts.
25///
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.
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 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
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.
48class ExternalASTMerger : public ExternalASTSource {
49public:
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;
59private:
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
68public:
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  struct ImporterSource {
84    ASTContext &AST;
85    FileManager &FM;
86    const OriginMap &OM;
87  };
88
89private:
90  /// The target for this ExtenralASTMerger.
91  ImporterTarget Target;
92
93public:
94  ExternalASTMerger(const ImporterTarget &Target,
95                    llvm::ArrayRef<ImporterSource> Sources);
96
97  /// Add a set of ASTContexts as possible origins.
98  ///
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).
102  ///
103  /// Ensures that Importers does not gain duplicate entries as a result.
104  void AddSources(llvm::ArrayRef<ImporterSource> Sources);
105
106  /// Remove a set of ASTContexts as possible origins.
107  ///
108  /// Sometimes an origin goes away (for example, if a source file gets
109  /// superseded by a newer version).
110  ///
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);
114
115  /// Implementation of the ExternalASTSource API.
116  bool FindExternalVisibleDeclsByName(const DeclContext *DC,
117                                      DeclarationName Name) override;
118
119  /// Implementation of the ExternalASTSource API.
120  void
121  FindExternalLexicalDecls(const DeclContext *DC,
122                           llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
123                           SmallVectorImpl<Decl *> &Result) override;
124
125  /// Implementation of the ExternalASTSource API.
126  void CompleteType(TagDecl *Tag) override;
127
128  /// Implementation of the ExternalASTSource API.
129  void CompleteType(ObjCInterfaceDecl *Interface) override;
130
131  /// Returns true if DC can be found in any source AST context.
132  bool CanComplete(DeclContext *DC);
133
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);
137
138  /// Regardless of any checks, override the Origin for a DeclContext.
139  void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);
140
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; }
144
145  /// Returns true if Importers contains an ASTImporter whose source is
146  /// OriginContext.
147  bool HasImporterForOrigin(ASTContext &OriginContext);
148
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);
153
154  /// Sets the current log stream.
155  void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
156private:
157  /// Records and origin in Origins.
158  void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
159                                  ASTImporter &importer);
160
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);
165
166public:
167  /// Log something if there is a logging callback installed.
168  llvm::raw_ostream &logs() { return *LogStream; }
169
170  /// True if the log stream is not llvm::nulls();
171  bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
172};
173
174} // end namespace clang
175
176#endif
177