summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/ExternalASTMerger.h
blob: d89189da04f02f0da323266beddf1bde10399f67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
//===--- ExternalASTMerger.h - Merging External AST Interface ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file declares the ExternalASTMerger, which vends a combination of ASTs
//  from several different ASTContext/FileManager pairs
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXTERNALASTMERGER_H
#define LLVM_CLANG_AST_EXTERNALASTMERGER_H

#include "clang/AST/ASTImporter.h"
#include "clang/AST/ExternalASTSource.h"
#include "llvm/Support/raw_ostream.h"

namespace clang {

/// ExternalASTSource implementation that merges information from several
/// ASTContexts.
///
/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import
/// (potentially incomplete) Decls and DeclContexts from the source ASTContexts
/// in response to ExternalASTSource API calls.
///
/// When lookup occurs in the resulting imported DeclContexts, the original
/// DeclContexts need to be queried.  Roughly, there are three cases here:
///
/// - The DeclContext of origin can be found by simple name lookup.  In this
///   case, no additional state is required.
///
/// - The DeclContext of origin is different from what would be found by name
///   lookup.  In this case, Origins contains an entry overriding lookup and
///   specifying the correct pair of DeclContext/ASTContext.
///
/// - The DeclContext of origin was determined by another ExterenalASTMerger.
///   (This is possible when the source ASTContext for one of the Importers has
///   its own ExternalASTMerger).  The origin must be properly forwarded in this
///   case.
///
/// ExternalASTMerger's job is to maintain the data structures necessary to
/// allow this.  The data structures themselves can be extracted (read-only) and
/// copied for re-use.
class ExternalASTMerger : public ExternalASTSource {
public:
  /// A single origin for a DeclContext.  Unlike Decls, DeclContexts do
  /// not allow their containing ASTContext to be determined in all cases.
  struct DCOrigin {
    DeclContext *DC;
    ASTContext *AST;
  };

  typedef std::map<const DeclContext *, DCOrigin> OriginMap;
  typedef std::vector<std::unique_ptr<ASTImporter>> ImporterVector;
private:
  /// One importer exists for each source.
  ImporterVector Importers;
  /// Overrides in case name lookup would return nothing or would return
  /// the wrong thing.
  OriginMap Origins;
  /// The installed log stream.
  llvm::raw_ostream *LogStream;

public:
  /// The target for an ExternalASTMerger.
  ///
  /// ASTImporters require both ASTContext and FileManager to be able to
  /// import SourceLocations properly.
  struct ImporterTarget {
    ASTContext &AST;
    FileManager &FM;
  };
  /// A source for an ExternalASTMerger.
  ///
  /// ASTImporters require both ASTContext and FileManager to be able to
  /// import SourceLocations properly.  Additionally, when import occurs for
  /// a DeclContext whose origin has been overridden, then this
  /// ExternalASTMerger must be able to determine that.
  struct ImporterSource {
    ASTContext &AST;
    FileManager &FM;
    const OriginMap &OM;
  };

private:
  /// The target for this ExtenralASTMerger.
  ImporterTarget Target;

public:
  ExternalASTMerger(const ImporterTarget &Target,
                    llvm::ArrayRef<ImporterSource> Sources);

  /// Add a set of ASTContexts as possible origins.
  ///
  /// Usually the set will be initialized in the constructor, but long-lived
  /// ExternalASTMergers may need to import from new sources (for example,
  /// newly-parsed source files).
  ///
  /// Ensures that Importers does not gain duplicate entries as a result.
  void AddSources(llvm::ArrayRef<ImporterSource> Sources);

  /// Remove a set of ASTContexts as possible origins.
  ///
  /// Sometimes an origin goes away (for example, if a source file gets
  /// superseded by a newer version).
  ///
  /// The caller is responsible for ensuring that this doesn't leave
  /// DeclContexts that can't be completed.
  void RemoveSources(llvm::ArrayRef<ImporterSource> Sources);

  /// Implementation of the ExternalASTSource API.
  bool FindExternalVisibleDeclsByName(const DeclContext *DC,
                                      DeclarationName Name) override;

  /// Implementation of the ExternalASTSource API.
  void
  FindExternalLexicalDecls(const DeclContext *DC,
                           llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
                           SmallVectorImpl<Decl *> &Result) override;

  /// Implementation of the ExternalASTSource API.
  void CompleteType(TagDecl *Tag) override;

  /// Implementation of the ExternalASTSource API.
  void CompleteType(ObjCInterfaceDecl *Interface) override;

  /// Returns true if DC can be found in any source AST context.
  bool CanComplete(DeclContext *DC);

  /// Records an origin in Origins only if name lookup would find
  /// something different or nothing at all.
  void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);

  /// Regardless of any checks, override the Origin for a DeclContext.
  void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin);

  /// Get a read-only view of the Origins map, for use in constructing
  /// an ImporterSource for another ExternalASTMerger.
  const OriginMap &GetOrigins() { return Origins; }

  /// Returns true if Importers contains an ASTImporter whose source is
  /// OriginContext.
  bool HasImporterForOrigin(ASTContext &OriginContext);

  /// Returns a reference to the ASTRImporter from Importers whose origin
  /// is OriginContext.  This allows manual import of ASTs while preserving the
  /// OriginMap correctly.
  ASTImporter &ImporterForOrigin(ASTContext &OriginContext);

  /// Sets the current log stream.
  void SetLogStream(llvm::raw_string_ostream &Stream) { LogStream = &Stream; }
private:
  /// Records and origin in Origins.
  void RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
                                  ASTImporter &importer);

  /// Performs an action for every DeclContext that is identified as
  /// corresponding (either by forced origin or by name lookup) to DC.
  template <typename CallbackType>
  void ForEachMatchingDC(const DeclContext *DC, CallbackType Callback);

public:
  /// Log something if there is a logging callback installed.
  llvm::raw_ostream &logs() { return *LogStream; }

  /// True if the log stream is not llvm::nulls();
  bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
};

} // end namespace clang

#endif