Coverage Report

Created: 2020-02-15 09:57

/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
195
        : AST(AST), FM(FM), OM(OM), Temporary(Temporary), Merger(Merger) {}
98
556
    ASTContext &getASTContext() const { return AST; }
99
260
    FileManager &getFileManager() const { return FM; }
100
130
    const OriginMap &getOriginMap() const { return OM; }
101
130
    bool isTemporary() const { return Temporary; }
102
260
    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
127
  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.50k
  bool LoggingEnabled() { return LogStream != &llvm::nulls(); }
199
};
200
201
} // end namespace clang
202
203
#endif