Coverage Report

Created: 2020-02-15 09:57

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ExternalASTMerger.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ExternalASTMerger.cpp - 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 implements the ExternalASTMerger, which vends a combination of
10
//  ASTs from several different ASTContext/FileManager pairs
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/AST/ASTContext.h"
15
#include "clang/AST/Decl.h"
16
#include "clang/AST/DeclCXX.h"
17
#include "clang/AST/DeclObjC.h"
18
#include "clang/AST/DeclTemplate.h"
19
#include "clang/AST/ExternalASTMerger.h"
20
21
using namespace clang;
22
23
namespace {
24
25
template <typename T> struct Source {
26
  T t;
27
11.1k
  Source(T t) : t(t) {}
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclContext const*>::Source(clang::DeclContext const*)
Line
Count
Source
27
4.95k
  Source(T t) : t(t) {}
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclarationName>::Source(clang::DeclarationName)
Line
Count
Source
27
1.65k
  Source(T t) : t(t) {}
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::TranslationUnitDecl*>::Source(clang::TranslationUnitDecl*)
Line
Count
Source
27
2.91k
  Source(T t) : t(t) {}
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclContext*>::Source(clang::DeclContext*)
Line
Count
Source
27
729
  Source(T t) : t(t) {}
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::NamedDecl*>::Source(clang::NamedDecl*)
Line
Count
Source
27
935
  Source(T t) : t(t) {}
28
6.27k
  operator T() { return t; }
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclContext const*>::operator clang::DeclContext const*()
Line
Count
Source
28
4.62k
  operator T() { return t; }
ExternalASTMerger.cpp:(anonymous namespace)::Source<clang::DeclContext*>::operator clang::DeclContext*()
Line
Count
Source
28
1.64k
  operator T() { return t; }
29
5.73k
  template <typename U = T> U &get() { return t; }
ExternalASTMerger.cpp:clang::DeclarationName& (anonymous namespace)::Source<clang::DeclarationName>::get<clang::DeclarationName>()
Line
Count
Source
29
1.65k
  template <typename U = T> U &get() { return t; }
ExternalASTMerger.cpp:clang::DeclContext const*& (anonymous namespace)::Source<clang::DeclContext const*>::get<clang::DeclContext const*>()
Line
Count
Source
29
4.07k
  template <typename U = T> U &get() { return t; }
30
1.94k
  template <typename U = T> const U &get() const { return t; }
31
2.91k
  template <typename U> operator Source<U>() { return Source<U>(t); }
32
};
33
34
typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
35
36
/// For the given DC, return the DC that is safe to perform lookups on.  This is
37
/// the DC we actually want to work with most of the time.
38
4.63k
const DeclContext *CanonicalizeDC(const DeclContext *DC) {
39
4.63k
  if (isa<LinkageSpecDecl>(DC))
40
6
    return DC->getRedeclContext();
41
4.62k
  return DC;
42
4.62k
}
43
44
Source<const DeclContext *>
45
LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
46
4.62k
                  ASTImporter &ReverseImporter) {
47
4.62k
  DC = CanonicalizeDC(DC);
48
4.62k
  if (DC->isTranslationUnit()) {
49
2.91k
    return SourceTU;
50
2.91k
  }
51
1.71k
  Source<const DeclContext *> SourceParentDC =
52
1.71k
      LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
53
1.71k
  if (!SourceParentDC) {
54
55
    // If we couldn't find the parent DC in this TranslationUnit, give up.
55
55
    return nullptr;
56
55
  }
57
1.66k
  auto *ND = cast<NamedDecl>(DC);
58
1.66k
  DeclarationName Name = ND->getDeclName();
59
1.66k
  auto SourceNameOrErr = ReverseImporter.Import(Name);
60
1.66k
  if (!SourceNameOrErr) {
61
2
    llvm::consumeError(SourceNameOrErr.takeError());
62
2
    return nullptr;
63
2
  }
64
1.65k
  Source<DeclarationName> SourceName = *SourceNameOrErr;
65
1.65k
  DeclContext::lookup_result SearchResult =
66
1.65k
      SourceParentDC.get()->lookup(SourceName.get());
67
1.65k
  size_t SearchResultSize = SearchResult.size();
68
1.65k
  if (SearchResultSize == 0 || 
SearchResultSize > 11.47k
) {
69
249
    // There are two cases here.  First, we might not find the name.
70
249
    // We might also find multiple copies, in which case we have no
71
249
    // guarantee that the one we wanted is the one we pick.  (E.g.,
72
249
    // if we have two specializations of the same template it is
73
249
    // very hard to determine which is the one you want.)
74
249
    //
75
249
    // The Origins map fixes this problem by allowing the origin to be
76
249
    // explicitly recorded, so we trigger that recording by returning
77
249
    // nothing (rather than a possibly-inaccurate guess) here.
78
249
    return nullptr;
79
1.40k
  } else {
80
1.40k
    NamedDecl *SearchResultDecl = SearchResult[0];
81
1.40k
    if (isa<DeclContext>(SearchResultDecl) &&
82
1.40k
        
SearchResultDecl->getKind() == DC->getDeclKind()1.35k
)
83
1.35k
      return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
84
55
    return nullptr; // This type of lookup is unsupported
85
55
  }
86
1.65k
}
87
88
/// A custom implementation of ASTImporter, for ExternalASTMerger's purposes.
89
///
90
/// There are several modifications:
91
///
92
/// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few
93
///   others), which instructs Clang to refer to ExternalASTMerger.  Also, it
94
///   forces MinimalImport to true, which is necessary to make this work.
95
/// - It maintains a reverse importer for use with names.  This allows lookup of
96
///   arbitrary names in the source context.
97
/// - It updates the ExternalASTMerger's origin map as needed whenever a
98
///   it sees a DeclContext.
99
class LazyASTImporter : public ASTImporter {
100
private:
101
  ExternalASTMerger &Parent;
102
  ASTImporter Reverse;
103
  const ExternalASTMerger::OriginMap &FromOrigins;
104
  /// @see ExternalASTMerger::ImporterSource::Temporary
105
  bool TemporarySource;
106
  /// Map of imported declarations back to the declarations they originated
107
  /// from.
108
  llvm::DenseMap<Decl *, Decl *> ToOrigin;
109
  /// @see ExternalASTMerger::ImporterSource::Merger
110
  ExternalASTMerger *SourceMerger;
111
0
  llvm::raw_ostream &logs() { return Parent.logs(); }
112
public:
113
  LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext,
114
                  FileManager &ToFileManager,
115
                  const ExternalASTMerger::ImporterSource &S,
116
                  std::shared_ptr<ASTImporterSharedState> SharedState)
117
      : ASTImporter(ToContext, ToFileManager, S.getASTContext(),
118
                    S.getFileManager(),
119
                    /*MinimalImport=*/true, SharedState),
120
        Parent(_Parent),
121
        Reverse(S.getASTContext(), S.getFileManager(), ToContext, ToFileManager,
122
                /*MinimalImport=*/true),
123
        FromOrigins(S.getOriginMap()), TemporarySource(S.isTemporary()),
124
130
        SourceMerger(S.getMerger()) {}
125
126
2.33k
  llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
127
2.33k
    if (!TemporarySource || 
!SourceMerger0
)
128
2.33k
      return ASTImporter::ImportImpl(FromD);
129
0
130
0
    // If we get here, then this source is importing from a temporary ASTContext
131
0
    // that also has another ExternalASTMerger attached. It could be
132
0
    // possible that the current ExternalASTMerger and the temporary ASTContext
133
0
    // share a common ImporterSource, which means that the temporary
134
0
    // AST could contain declarations that were imported from a source
135
0
    // that this ExternalASTMerger can access directly. Instead of importing
136
0
    // such declarations from the temporary ASTContext, they should instead
137
0
    // be directly imported by this ExternalASTMerger from the original
138
0
    // source. This way the ExternalASTMerger can safely do a minimal import
139
0
    // without creating incomplete declarations originated from a temporary
140
0
    // ASTContext. If we would try to complete such declarations later on, we
141
0
    // would fail to do so as their temporary AST could be deleted (which means
142
0
    // that the missing parts of the minimally imported declaration in that
143
0
    // ASTContext were also deleted).
144
0
    //
145
0
    // The following code tracks back any declaration that needs to be
146
0
    // imported from the temporary ASTContext to a persistent ASTContext.
147
0
    // Then the ExternalASTMerger tries to import from the persistent
148
0
    // ASTContext directly by using the associated ASTImporter. If that
149
0
    // succeeds, this ASTImporter just maps the declarations imported by
150
0
    // the other (persistent) ASTImporter to this (temporary) ASTImporter.
151
0
    // The steps can be visualized like this:
152
0
    //
153
0
    //  Target AST <--- 3. Indirect import --- Persistent AST
154
0
    //       ^            of persistent decl        ^
155
0
    //       |                                      |
156
0
    // 1. Current import           2. Tracking back to persistent decl
157
0
    // 4. Map persistent decl                       |
158
0
    //  & pretend we imported.                      |
159
0
    //       |                                      |
160
0
    // Temporary AST -------------------------------'
161
0
162
0
    // First, ask the ExternalASTMerger of the source where the temporary
163
0
    // declaration originated from.
164
0
    Decl *Persistent = SourceMerger->FindOriginalDecl(FromD);
165
0
    // FromD isn't from a persistent AST, so just do a normal import.
166
0
    if (!Persistent)
167
0
      return ASTImporter::ImportImpl(FromD);
168
0
    // Now ask the current ExternalASTMerger to try import the persistent
169
0
    // declaration into the target.
170
0
    ASTContext &PersistentCtx = Persistent->getASTContext();
171
0
    ASTImporter &OtherImporter = Parent.ImporterForOrigin(PersistentCtx);
172
0
    // Check that we never end up in the current Importer again.
173
0
    assert((&PersistentCtx != &getFromContext()) && (&OtherImporter != this) &&
174
0
           "Delegated to same Importer?");
175
0
    auto DeclOrErr = OtherImporter.Import(Persistent);
176
0
    // Errors when importing the persistent decl are treated as if we
177
0
    // had errors with importing the temporary decl.
178
0
    if (!DeclOrErr)
179
0
      return DeclOrErr.takeError();
180
0
    Decl *D = *DeclOrErr;
181
0
    // Tell the current ASTImporter that this has already been imported
182
0
    // to prevent any further queries for the temporary decl.
183
0
    MapImported(FromD, D);
184
0
    return D;
185
0
  }
186
187
  /// Implements the ASTImporter interface for tracking back a declaration
188
  /// to its original declaration it came from.
189
4
  Decl *GetOriginalDecl(Decl *To) override {
190
4
    auto It = ToOrigin.find(To);
191
4
    if (It != ToOrigin.end())
192
0
      return It->second;
193
4
    return nullptr;
194
4
  }
195
196
  /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin
197
  /// map is kept up to date.  Also set the appropriate flags.
198
2.33k
  void Imported(Decl *From, Decl *To) override {
199
2.33k
    ToOrigin[To] = From;
200
2.33k
201
2.33k
    if (auto *ToDC = dyn_cast<DeclContext>(To)) {
202
729
      const bool LoggingEnabled = Parent.LoggingEnabled();
203
729
      if (LoggingEnabled)
204
0
        logs() << "(ExternalASTMerger*)" << (void*)&Parent
205
0
               << " imported (DeclContext*)" << (void*)ToDC
206
0
               << ", (ASTContext*)" << (void*)&getToContext()
207
0
               << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From)
208
0
               << ", (ASTContext*)" << (void*)&getFromContext()
209
0
               << "\n";
210
729
      Source<DeclContext *> FromDC(
211
729
          cast<DeclContext>(From)->getPrimaryContext());
212
729
      if (FromOrigins.count(FromDC) &&
213
729
          
Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)184
) {
214
4
        if (LoggingEnabled)
215
0
          logs() << "(ExternalASTMerger*)" << (void*)&Parent
216
0
                 << " forced origin (DeclContext*)"
217
0
                 << (void*)FromOrigins.at(FromDC).DC
218
0
                 << ", (ASTContext*)"
219
0
                 << (void*)FromOrigins.at(FromDC).AST
220
0
                 << "\n";
221
4
        Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
222
725
      } else {
223
725
        if (LoggingEnabled)
224
0
          logs() << "(ExternalASTMerger*)" << (void*)&Parent
225
0
                 << " maybe recording origin (DeclContext*)" << (void*)FromDC
226
0
                 << ", (ASTContext*)" << (void*)&getFromContext()
227
0
                 << "\n";
228
725
        Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()});
229
725
      }
230
729
    }
231
2.33k
    if (auto *ToTag = dyn_cast<TagDecl>(To)) {
232
462
      ToTag->setHasExternalLexicalStorage();
233
462
      ToTag->getPrimaryContext()->setMustBuildLookupTable();
234
462
      assert(Parent.CanComplete(ToTag));
235
1.87k
    } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
236
24
      ToNamespace->setHasExternalVisibleStorage();
237
24
      assert(Parent.CanComplete(ToNamespace));
238
1.85k
    } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
239
30
      ToContainer->setHasExternalLexicalStorage();
240
30
      ToContainer->getPrimaryContext()->setMustBuildLookupTable();
241
30
      assert(Parent.CanComplete(ToContainer));
242
30
    }
243
2.33k
  }
244
3.23k
  ASTImporter &GetReverse() { return Reverse; }
245
};
246
247
935
bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
248
935
  if (isa<FunctionDecl>(C.first.get()))
249
73
    return false;
250
862
  return llvm::any_of(Decls, [&](const Candidate &D) {
251
76
    return C.first.get()->getKind() == D.first.get()->getKind();
252
76
  });
253
862
}
254
255
} // end namespace
256
257
1.05k
ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) {
258
1.05k
  for (const std::unique_ptr<ASTImporter> &I : Importers)
259
1.09k
    if (&I->getFromContext() == &OriginContext)
260
1.05k
      return *I;
261
1.05k
  
llvm_unreachable0
("We should have an importer for this origin!");
262
1.05k
}
263
264
namespace {
265
LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger,
266
1.05k
                                   ASTContext &OriginContext) {
267
1.05k
  return static_cast<LazyASTImporter &>(
268
1.05k
      Merger.ImporterForOrigin(OriginContext));
269
1.05k
}
270
}
271
272
184
bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) {
273
184
  for (const std::unique_ptr<ASTImporter> &I : Importers)
274
212
    if (&I->getFromContext() == &OriginContext)
275
4
      return true;
276
184
  
return false180
;
277
184
}
278
279
template <typename CallbackType>
280
void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC,
281
2.35k
                                          CallbackType Callback) {
282
2.35k
  if (Origins.count(DC)) {
283
325
    ExternalASTMerger::DCOrigin Origin = Origins[DC];
284
325
    LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
285
325
    Callback(Importer, Importer.GetReverse(), Origin.DC);
286
2.02k
  } else {
287
2.02k
    bool DidCallback = false;
288
2.18k
    for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
289
2.18k
      Source<TranslationUnitDecl *> SourceTU =
290
2.18k
          Importer->getFromContext().getTranslationUnitDecl();
291
2.18k
      ASTImporter &Reverse =
292
2.18k
          static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
293
2.18k
      if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
294
2.16k
        DidCallback = true;
295
2.16k
        if (Callback(*Importer, Reverse, SourceDC))
296
327
          break;
297
2.16k
      }
298
2.18k
    }
299
2.02k
    if (!DidCallback && 
LoggingEnabled()0
)
300
0
      logs() << "(ExternalASTMerger*)" << (void*)this
301
0
             << " asserting for (DeclContext*)" << (const void*)DC
302
0
             << ", (ASTContext*)" << (void*)&Target.AST
303
0
             << "\n";
304
2.02k
    assert(DidCallback && "Couldn't find a source context matching our DC");
305
2.02k
  }
306
2.35k
}
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::CompleteType(clang::TagDecl*)::$_0>(clang::DeclContext const*, clang::ExternalASTMerger::CompleteType(clang::TagDecl*)::$_0)
Line
Count
Source
281
6
                                          CallbackType Callback) {
282
6
  if (Origins.count(DC)) {
283
0
    ExternalASTMerger::DCOrigin Origin = Origins[DC];
284
0
    LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
285
0
    Callback(Importer, Importer.GetReverse(), Origin.DC);
286
6
  } else {
287
6
    bool DidCallback = false;
288
8
    for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
289
8
      Source<TranslationUnitDecl *> SourceTU =
290
8
          Importer->getFromContext().getTranslationUnitDecl();
291
8
      ASTImporter &Reverse =
292
8
          static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
293
8
      if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
294
8
        DidCallback = true;
295
8
        if (Callback(*Importer, Reverse, SourceDC))
296
4
          break;
297
8
      }
298
8
    }
299
6
    if (!DidCallback && 
LoggingEnabled()0
)
300
0
      logs() << "(ExternalASTMerger*)" << (void*)this
301
0
             << " asserting for (DeclContext*)" << (const void*)DC
302
0
             << ", (ASTContext*)" << (void*)&Target.AST
303
0
             << "\n";
304
6
    assert(DidCallback && "Couldn't find a source context matching our DC");
305
6
  }
306
6
}
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::CompleteType(clang::ObjCInterfaceDecl*)::$_1>(clang::DeclContext const*, clang::ExternalASTMerger::CompleteType(clang::ObjCInterfaceDecl*)::$_1)
Line
Count
Source
281
3
                                          CallbackType Callback) {
282
3
  if (Origins.count(DC)) {
283
0
    ExternalASTMerger::DCOrigin Origin = Origins[DC];
284
0
    LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
285
0
    Callback(Importer, Importer.GetReverse(), Origin.DC);
286
3
  } else {
287
3
    bool DidCallback = false;
288
4
    for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
289
4
      Source<TranslationUnitDecl *> SourceTU =
290
4
          Importer->getFromContext().getTranslationUnitDecl();
291
4
      ASTImporter &Reverse =
292
4
          static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
293
4
      if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
294
4
        DidCallback = true;
295
4
        if (Callback(*Importer, Reverse, SourceDC))
296
2
          break;
297
4
      }
298
4
    }
299
3
    if (!DidCallback && 
LoggingEnabled()0
)
300
0
      logs() << "(ExternalASTMerger*)" << (void*)this
301
0
             << " asserting for (DeclContext*)" << (const void*)DC
302
0
             << ", (ASTContext*)" << (void*)&Target.AST
303
0
             << "\n";
304
3
    assert(DidCallback && "Couldn't find a source context matching our DC");
305
3
  }
306
3
}
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::CanComplete(clang::DeclContext*)::$_2>(clang::DeclContext const*, clang::ExternalASTMerger::CanComplete(clang::DeclContext*)::$_2)
Line
Count
Source
281
516
                                          CallbackType Callback) {
282
516
  if (Origins.count(DC)) {
283
195
    ExternalASTMerger::DCOrigin Origin = Origins[DC];
284
195
    LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
285
195
    Callback(Importer, Importer.GetReverse(), Origin.DC);
286
321
  } else {
287
321
    bool DidCallback = false;
288
331
    for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
289
331
      Source<TranslationUnitDecl *> SourceTU =
290
331
          Importer->getFromContext().getTranslationUnitDecl();
291
331
      ASTImporter &Reverse =
292
331
          static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
293
331
      if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
294
321
        DidCallback = true;
295
321
        if (Callback(*Importer, Reverse, SourceDC))
296
321
          break;
297
321
      }
298
331
    }
299
321
    if (!DidCallback && 
LoggingEnabled()0
)
300
0
      logs() << "(ExternalASTMerger*)" << (void*)this
301
0
             << " asserting for (DeclContext*)" << (const void*)DC
302
0
             << ", (ASTContext*)" << (void*)&Target.AST
303
0
             << "\n";
304
321
    assert(DidCallback && "Couldn't find a source context matching our DC");
305
321
  }
306
516
}
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::FindExternalVisibleDeclsByName(clang::DeclContext const*, clang::DeclarationName)::$_5>(clang::DeclContext const*, clang::ExternalASTMerger::FindExternalVisibleDeclsByName(clang::DeclContext const*, clang::DeclarationName)::$_5)
Line
Count
Source
281
1.55k
                                          CallbackType Callback) {
282
1.55k
  if (Origins.count(DC)) {
283
30
    ExternalASTMerger::DCOrigin Origin = Origins[DC];
284
30
    LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
285
30
    Callback(Importer, Importer.GetReverse(), Origin.DC);
286
1.52k
  } else {
287
1.52k
    bool DidCallback = false;
288
1.65k
    for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
289
1.65k
      Source<TranslationUnitDecl *> SourceTU =
290
1.65k
          Importer->getFromContext().getTranslationUnitDecl();
291
1.65k
      ASTImporter &Reverse =
292
1.65k
          static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
293
1.65k
      if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
294
1.65k
        DidCallback = true;
295
1.65k
        if (Callback(*Importer, Reverse, SourceDC))
296
0
          break;
297
1.65k
      }
298
1.65k
    }
299
1.52k
    if (!DidCallback && 
LoggingEnabled()0
)
300
0
      logs() << "(ExternalASTMerger*)" << (void*)this
301
0
             << " asserting for (DeclContext*)" << (const void*)DC
302
0
             << ", (ASTContext*)" << (void*)&Target.AST
303
0
             << "\n";
304
1.52k
    assert(DidCallback && "Couldn't find a source context matching our DC");
305
1.52k
  }
306
1.55k
}
ExternalASTMerger.cpp:void clang::ExternalASTMerger::ForEachMatchingDC<clang::ExternalASTMerger::FindExternalLexicalDecls(clang::DeclContext const*, llvm::function_ref<bool (clang::Decl::Kind)>, llvm::SmallVectorImpl<clang::Decl*>&)::$_6>(clang::DeclContext const*, clang::ExternalASTMerger::FindExternalLexicalDecls(clang::DeclContext const*, llvm::function_ref<bool (clang::Decl::Kind)>, llvm::SmallVectorImpl<clang::Decl*>&)::$_6)
Line
Count
Source
281
272
                                          CallbackType Callback) {
282
272
  if (Origins.count(DC)) {
283
100
    ExternalASTMerger::DCOrigin Origin = Origins[DC];
284
100
    LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
285
100
    Callback(Importer, Importer.GetReverse(), Origin.DC);
286
172
  } else {
287
172
    bool DidCallback = false;
288
192
    for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
289
192
      Source<TranslationUnitDecl *> SourceTU =
290
192
          Importer->getFromContext().getTranslationUnitDecl();
291
192
      ASTImporter &Reverse =
292
192
          static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
293
192
      if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
294
182
        DidCallback = true;
295
182
        if (Callback(*Importer, Reverse, SourceDC))
296
0
          break;
297
182
      }
298
192
    }
299
172
    if (!DidCallback && 
LoggingEnabled()0
)
300
0
      logs() << "(ExternalASTMerger*)" << (void*)this
301
0
             << " asserting for (DeclContext*)" << (const void*)DC
302
0
             << ", (ASTContext*)" << (void*)&Target.AST
303
0
             << "\n";
304
172
    assert(DidCallback && "Couldn't find a source context matching our DC");
305
172
  }
306
272
}
307
308
6
void ExternalASTMerger::CompleteType(TagDecl *Tag) {
309
6
  assert(Tag->hasExternalLexicalStorage());
310
6
  ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse,
311
8
                             Source<const DeclContext *> SourceDC) -> bool {
312
8
    auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get()));
313
8
    if (SourceTag->hasExternalLexicalStorage())
314
4
      SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
315
8
    if (!SourceTag->getDefinition())
316
4
      return false;
317
4
    Forward.MapImported(SourceTag, Tag);
318
4
    if (llvm::Error Err = Forward.ImportDefinition(SourceTag))
319
0
      llvm::consumeError(std::move(Err));
320
4
    Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
321
4
    return true;
322
4
  });
323
6
}
324
325
3
void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
326
3
  assert(Interface->hasExternalLexicalStorage());
327
3
  ForEachMatchingDC(
328
3
      Interface, [&](ASTImporter &Forward, ASTImporter &Reverse,
329
4
                     Source<const DeclContext *> SourceDC) -> bool {
330
4
        auto *SourceInterface = const_cast<ObjCInterfaceDecl *>(
331
4
            cast<ObjCInterfaceDecl>(SourceDC.get()));
332
4
        if (SourceInterface->hasExternalLexicalStorage())
333
2
          SourceInterface->getASTContext().getExternalSource()->CompleteType(
334
2
              SourceInterface);
335
4
        if (!SourceInterface->getDefinition())
336
2
          return false;
337
2
        Forward.MapImported(SourceInterface, Interface);
338
2
        if (llvm::Error Err = Forward.ImportDefinition(SourceInterface))
339
0
          llvm::consumeError(std::move(Err));
340
2
        return true;
341
2
      });
342
3
}
343
344
516
bool ExternalASTMerger::CanComplete(DeclContext *Interface) {
345
516
  assert(Interface->hasExternalLexicalStorage() ||
346
516
         Interface->hasExternalVisibleStorage());
347
516
  bool FoundMatchingDC = false;
348
516
  ForEachMatchingDC(Interface,
349
516
                    [&](ASTImporter &Forward, ASTImporter &Reverse,
350
516
                        Source<const DeclContext *> SourceDC) -> bool {
351
516
                      FoundMatchingDC = true;
352
516
                      return true;
353
516
                    });
354
516
  return FoundMatchingDC;
355
516
}
356
357
namespace {
358
1.33k
bool IsSameDC(const DeclContext *D1, const DeclContext *D2) {
359
1.33k
  if (isa<ObjCContainerDecl>(D1) && 
isa<ObjCContainerDecl>(D2)40
)
360
40
    return true; // There are many cases where Objective-C is ambiguous.
361
1.29k
  if (auto *T1 = dyn_cast<TagDecl>(D1))
362
1.16k
    if (auto *T2 = dyn_cast<TagDecl>(D2))
363
1.16k
      if (T1->getFirstDecl() == T2->getFirstDecl())
364
1.16k
        return true;
365
134
  return D1 == D2 || 
D1 == CanonicalizeDC(D2)2
;
366
134
}
367
}
368
369
void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC,
370
725
                                          DCOrigin Origin) {
371
725
  LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
372
725
  ASTImporter &Reverse = Importer.GetReverse();
373
725
  Source<const DeclContext *> FoundFromDC =
374
725
      LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse);
375
725
  const bool DoRecord = !FoundFromDC || 
!IsSameDC(FoundFromDC.get(), Origin.DC)442
;
376
725
  if (DoRecord)
377
283
    RecordOriginImpl(ToDC, Origin, Importer);
378
725
  if (LoggingEnabled())
379
0
    logs() << "(ExternalASTMerger*)" << (void*)this
380
0
             << (DoRecord ? " decided " : " decided NOT")
381
0
             << " to record origin (DeclContext*)" << (void*)Origin.DC
382
0
             << ", (ASTContext*)" << (void*)&Origin.AST
383
0
             << "\n";
384
725
}
385
386
void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC,
387
4
                                          DCOrigin Origin) {
388
4
  RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST));
389
4
}
390
391
void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
392
287
                                         ASTImporter &Importer) {
393
287
  Origins[ToDC] = Origin;
394
287
  Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
395
287
}
396
397
ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
398
119
                                     llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) {
399
119
  SharedState = std::make_shared<ASTImporterSharedState>(
400
119
      *Target.AST.getTranslationUnitDecl());
401
119
  AddSources(Sources);
402
119
}
403
404
0
Decl *ExternalASTMerger::FindOriginalDecl(Decl *D) {
405
0
  assert(&D->getASTContext() == &Target.AST);
406
0
  for (const auto &I : Importers)
407
0
    if (auto Result = I->GetOriginalDecl(D))
408
0
      return Result;
409
0
  return nullptr;
410
0
}
411
412
119
void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) {
413
130
  for (const ImporterSource &S : Sources) {
414
130
    assert(&S.getASTContext() != &Target.AST);
415
130
    // Check that the associated merger actually imports into the source AST.
416
130
    assert(!S.getMerger() || &S.getMerger()->Target.AST == &S.getASTContext());
417
130
    Importers.push_back(std::make_unique<LazyASTImporter>(
418
130
        *this, Target.AST, Target.FM, S, SharedState));
419
130
  }
420
119
}
421
422
54
void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) {
423
54
  if (LoggingEnabled())
424
0
    for (const ImporterSource &S : Sources)
425
0
      logs() << "(ExternalASTMerger*)" << (void *)this
426
0
             << " removing source (ASTContext*)" << (void *)&S.getASTContext()
427
0
             << "\n";
428
54
  Importers.erase(
429
54
      std::remove_if(Importers.begin(), Importers.end(),
430
65
                     [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool {
431
79
                       for (const ImporterSource &S : Sources) {
432
79
                         if (&Importer->getFromContext() == &S.getASTContext())
433
65
                           return true;
434
79
                       }
435
65
                       
return false0
;
436
65
                     }),
437
54
      Importers.end());
438
133
  for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
439
79
    std::pair<const DeclContext *, DCOrigin> Origin = *OI;
440
79
    bool Erase = false;
441
87
    for (const ImporterSource &S : Sources) {
442
87
      if (&S.getASTContext() == Origin.second.AST) {
443
79
        Erase = true;
444
79
        break;
445
79
      }
446
87
    }
447
79
    if (Erase)
448
79
      OI = Origins.erase(OI);
449
0
    else
450
0
      ++OI;
451
79
  }
452
54
}
453
454
template <typename DeclTy>
455
14
static bool importSpecializations(DeclTy *D, ASTImporter *Importer) {
456
14
  for (auto *Spec : D->specializations()) {
457
8
    auto ImportedSpecOrError = Importer->Import(Spec);
458
8
    if (!ImportedSpecOrError) {
459
0
      llvm::consumeError(ImportedSpecOrError.takeError());
460
0
      return true;
461
0
    }
462
8
  }
463
14
  return false;
464
14
}
ExternalASTMerger.cpp:bool importSpecializations<clang::FunctionTemplateDecl>(clang::FunctionTemplateDecl*, clang::ASTImporter*)
Line
Count
Source
455
4
static bool importSpecializations(DeclTy *D, ASTImporter *Importer) {
456
4
  for (auto *Spec : D->specializations()) {
457
4
    auto ImportedSpecOrError = Importer->Import(Spec);
458
4
    if (!ImportedSpecOrError) {
459
0
      llvm::consumeError(ImportedSpecOrError.takeError());
460
0
      return true;
461
0
    }
462
4
  }
463
4
  return false;
464
4
}
ExternalASTMerger.cpp:bool importSpecializations<clang::ClassTemplateDecl>(clang::ClassTemplateDecl*, clang::ASTImporter*)
Line
Count
Source
455
10
static bool importSpecializations(DeclTy *D, ASTImporter *Importer) {
456
10
  for (auto *Spec : D->specializations()) {
457
4
    auto ImportedSpecOrError = Importer->Import(Spec);
458
4
    if (!ImportedSpecOrError) {
459
0
      llvm::consumeError(ImportedSpecOrError.takeError());
460
0
      return true;
461
0
    }
462
4
  }
463
10
  return false;
464
10
}
Unexecuted instantiation: ExternalASTMerger.cpp:bool importSpecializations<clang::VarTemplateDecl>(clang::VarTemplateDecl*, clang::ASTImporter*)
465
466
/// Imports specializations from template declarations that can be specialized.
467
860
static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) {
468
860
  if (!isa<TemplateDecl>(D))
469
838
    return false;
470
22
  if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
471
4
    return importSpecializations(FunctionTD, Importer);
472
18
  else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
473
10
    return importSpecializations(ClassTD, Importer);
474
8
  else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D))
475
0
    return importSpecializations(VarTD, Importer);
476
8
  return false;
477
8
}
478
479
bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
480
1.55k
                                                       DeclarationName Name) {
481
1.55k
  llvm::SmallVector<NamedDecl *, 1> Decls;
482
1.55k
  llvm::SmallVector<Candidate, 4> Candidates;
483
1.55k
484
1.55k
  auto FilterFoundDecl = [&Candidates](const Candidate &C) {
485
935
   if (!HasDeclOfSameType(Candidates, C))
486
860
     Candidates.push_back(C);
487
935
  };
488
1.55k
489
1.55k
  ForEachMatchingDC(DC,
490
1.55k
                    [&](ASTImporter &Forward, ASTImporter &Reverse,
491
1.68k
                        Source<const DeclContext *> SourceDC) -> bool {
492
1.68k
                      auto FromNameOrErr = Reverse.Import(Name);
493
1.68k
                      if (!FromNameOrErr) {
494
0
                        llvm::consumeError(FromNameOrErr.takeError());
495
0
                        return false;
496
0
                      }
497
1.68k
                      DeclContextLookupResult Result =
498
1.68k
                          SourceDC.get()->lookup(*FromNameOrErr);
499
1.68k
                      for (NamedDecl *FromD : Result) {
500
935
                        FilterFoundDecl(std::make_pair(FromD, &Forward));
501
935
                      }
502
1.68k
                      return false;
503
1.68k
                    });
504
1.55k
505
1.55k
  if (Candidates.empty())
506
701
    return false;
507
856
508
856
  Decls.reserve(Candidates.size());
509
860
  for (const Candidate &C : Candidates) {
510
860
    Decl *LookupRes = C.first.get();
511
860
    ASTImporter *Importer = C.second;
512
860
    auto NDOrErr = Importer->Import(LookupRes);
513
860
    NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr)));
514
860
    assert(ND);
515
860
    // If we don't import specialization, they are not available via lookup
516
860
    // because the lookup result is imported TemplateDecl and it does not
517
860
    // reference its specializations until they are imported explicitly.
518
860
    bool IsSpecImportFailed =
519
860
        importSpecializationsIfNeeded(LookupRes, Importer);
520
860
    assert(!IsSpecImportFailed);
521
860
    (void)IsSpecImportFailed;
522
860
    Decls.push_back(ND);
523
860
  }
524
856
  SetExternalVisibleDeclsForName(DC, Name, Decls);
525
856
  return true;
526
856
}
527
528
void ExternalASTMerger::FindExternalLexicalDecls(
529
    const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
530
272
    SmallVectorImpl<Decl *> &Result) {
531
272
  ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
532
282
                            Source<const DeclContext *> SourceDC) -> bool {
533
940
    for (const Decl *SourceDecl : SourceDC.get()->decls()) {
534
940
      if (IsKindWeWant(SourceDecl->getKind())) {
535
895
        auto ImportedDeclOrErr = Forward.Import(SourceDecl);
536
895
        if (ImportedDeclOrErr)
537
895
          assert(!(*ImportedDeclOrErr) ||
538
895
                 IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
539
895
        else
540
895
          
llvm::consumeError(ImportedDeclOrErr.takeError())0
;
541
895
      }
542
940
    }
543
282
    return false;
544
282
  });
545
272
}
546