clang  5.0.0
ExternalASTMerger.cpp
Go to the documentation of this file.
1 //===- ExternalASTMerger.cpp - 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 implements the ExternalASTMerger, which vends a combination of
11 // ASTs from several different ASTContext/FileManager pairs
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclObjC.h"
19 
20 using namespace clang;
21 
22 namespace {
23 
24 template <typename T> struct Source {
25  T t;
26  Source(T t) : t(t) {}
27  operator T() { return t; }
28  template <typename U = T> U &get() { return t; }
29  template <typename U = T> const U &get() const { return t; }
30  template <typename U> operator Source<U>() { return Source<U>(t); }
31 };
32 
33 typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
34 
35 class LazyASTImporter : public ASTImporter {
36 public:
37  LazyASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
38  ASTContext &FromContext, FileManager &FromFileManager)
39  : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
40  /*MinimalImport=*/true) {}
41  Decl *Imported(Decl *From, Decl *To) override {
42  if (auto ToTag = dyn_cast<TagDecl>(To)) {
43  ToTag->setHasExternalLexicalStorage();
44  ToTag->setMustBuildLookupTable();
45  } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
46  ToNamespace->setHasExternalVisibleStorage();
47  }
48  return ASTImporter::Imported(From, To);
49  }
50 };
51 
52 Source<const DeclContext *>
53 LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
54  ASTImporter &ReverseImporter) {
55  if (DC->isTranslationUnit()) {
56  return SourceTU;
57  }
58  Source<const DeclContext *> SourceParentDC =
59  LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
60  if (!SourceParentDC) {
61  // If we couldn't find the parent DC in this TranslationUnit, give up.
62  return nullptr;
63  }
64  auto ND = cast<NamedDecl>(DC);
65  DeclarationName Name = ND->getDeclName();
66  Source<DeclarationName> SourceName = ReverseImporter.Import(Name);
67  DeclContext::lookup_result SearchResult =
68  SourceParentDC.get()->lookup(SourceName.get());
69  size_t SearchResultSize = SearchResult.size();
70  // Handle multiple candidates once we have a test for it.
71  // This may turn up when we import template specializations correctly.
72  assert(SearchResultSize < 2);
73  if (SearchResultSize == 0) {
74  // couldn't find the name, so we have to give up
75  return nullptr;
76  } else {
77  NamedDecl *SearchResultDecl = SearchResult[0];
78  return dyn_cast<DeclContext>(SearchResultDecl);
79  }
80 }
81 
82 bool IsForwardDeclaration(Decl *D) {
83  assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case
84  if (auto TD = dyn_cast<TagDecl>(D)) {
85  return !TD->isThisDeclarationADefinition();
86  } else if (auto FD = dyn_cast<FunctionDecl>(D)) {
87  return !FD->isThisDeclarationADefinition();
88  } else {
89  return false;
90  }
91 }
92 
93 template <typename CallbackType>
94 void ForEachMatchingDC(
95  const DeclContext *DC,
97  CallbackType Callback) {
98  for (const ExternalASTMerger::ImporterPair &IP : Importers) {
99  Source<TranslationUnitDecl *> SourceTU =
100  IP.Forward->getFromContext().getTranslationUnitDecl();
101  if (auto SourceDC = LookupSameContext(SourceTU, DC, *IP.Reverse))
102  Callback(IP, SourceDC);
103  }
104 }
105 
106 bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
107  return llvm::any_of(Decls, [&](const Candidate &D) {
108  return C.first.get()->getKind() == D.first.get()->getKind();
109  });
110 }
111 } // end namespace
112 
115  for (const ImporterEndpoint &S : Sources) {
116  Importers.push_back(
117  {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM),
118  llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM,
119  /*MinimalImport=*/true)});
120  }
121 }
122 
124  DeclarationName Name) {
126  llvm::SmallVector<Candidate, 4> CompleteDecls;
127  llvm::SmallVector<Candidate, 4> ForwardDecls;
128 
129  auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) {
130  if (IsForwardDeclaration(C.first.get())) {
131  if (!HasDeclOfSameType(ForwardDecls, C)) {
132  ForwardDecls.push_back(C);
133  }
134  } else {
135  CompleteDecls.push_back(C);
136  }
137  };
138 
139  ForEachMatchingDC(
140  DC, Importers,
141  [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
142  DeclarationName FromName = IP.Reverse->Import(Name);
143  DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
144  for (NamedDecl *FromD : Result) {
145  FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
146  }
147  });
148 
149  llvm::ArrayRef<Candidate> DeclsToReport =
150  CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
151 
152  if (DeclsToReport.empty()) {
153  return false;
154  }
155 
156  Decls.reserve(DeclsToReport.size());
157  for (const Candidate &C : DeclsToReport) {
158  NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get()));
159  assert(d);
160  Decls.push_back(d);
161  }
162  SetExternalVisibleDeclsForName(DC, Name, Decls);
163  return true;
164 }
165 
167  const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
168  SmallVectorImpl<Decl *> &Result) {
169  ForEachMatchingDC(
170  DC, Importers,
171  [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
172  for (const Decl *SourceDecl : SourceDC.get()->decls()) {
173  if (IsKindWeWant(SourceDecl->getKind())) {
174  Decl *ImportedDecl =
175  IP.Forward->Import(const_cast<Decl *>(SourceDecl));
176  assert(ImportedDecl->getDeclContext() == DC);
177  (void)ImportedDecl;
178  }
179  }
180  });
181 }
182 
Defines the clang::ASTContext interface.
Implements support for file system lookup, file system caching, and directory search management...
Definition: FileManager.h:116
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, ArrayRef< NamedDecl * > Decls)
Definition: DeclBase.cpp:1258
QualType Import(QualType FromT)
Import the given type from the "from" context into the "to" context.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:128
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1146
bool isTranslationUnit() const
Definition: DeclBase.h:1364
std::unique_ptr< ASTImporter > Forward
bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override
Find all declarations with the given name in the given context, and add them to the context by callin...
MatchFinder::MatchCallback * Callback
DeclContext * getDeclContext()
Definition: DeclBase.h:416
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1294
The result type of a method or function.
void FindExternalLexicalDecls(const DeclContext *DC, llvm::function_ref< bool(Decl::Kind)> IsKindWeWant, SmallVectorImpl< Decl * > &Result) override
Finds all declarations lexically contained within the given DeclContext, after applying an optional f...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1215
StringRef Name
Definition: USRFinder.cpp:123
virtual Decl * Imported(Decl *From, Decl *To)
Note that we have imported the "from" declaration by mapping it to the (potentially-newly-created) "t...
DeclarationName - The name of a declaration.
Imports selected nodes from one AST context into another context, merging AST nodes where appropriate...
Definition: ASTImporter.h:40
ExternalASTMerger(const ImporterEndpoint &Target, llvm::ArrayRef< ImporterEndpoint > Sources)
Kind
Lists the kind of concrete classes of Decl.
Definition: DeclBase.h:84
std::unique_ptr< ASTImporter > Reverse
#define true
Definition: stdbool.h:32
NamedDecl - This represents a decl with a name.
Definition: Decl.h:213