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" 18 #include "clang/AST/ExternalASTMerger.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 } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) { 45 ToNamespace->setHasExternalVisibleStorage(); 46 } 47 return ASTImporter::Imported(From, To); 48 } 49 }; 50 51 Source<const DeclContext *> 52 LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC, 53 ASTImporter &ReverseImporter) { 54 if (DC->isTranslationUnit()) { 55 return SourceTU; 56 } 57 Source<const DeclContext *> SourceParentDC = 58 LookupSameContext(SourceTU, DC->getParent(), ReverseImporter); 59 if (!SourceParentDC) { 60 // If we couldn't find the parent DC in this TranslationUnit, give up. 61 return nullptr; 62 } 63 auto ND = cast<NamedDecl>(DC); 64 DeclarationName Name = ND->getDeclName(); 65 Source<DeclarationName> SourceName = ReverseImporter.Import(Name); 66 DeclContext::lookup_result SearchResult = 67 SourceParentDC.get()->lookup(SourceName.get()); 68 size_t SearchResultSize = SearchResult.size(); 69 // Handle multiple candidates once we have a test for it. 70 // This may turn up when we import template specializations correctly. 71 assert(SearchResultSize < 2); 72 if (SearchResultSize == 0) { 73 // couldn't find the name, so we have to give up 74 return nullptr; 75 } else { 76 NamedDecl *SearchResultDecl = SearchResult[0]; 77 return dyn_cast<DeclContext>(SearchResultDecl); 78 } 79 } 80 81 bool IsForwardDeclaration(Decl *D) { 82 assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case 83 if (auto TD = dyn_cast<TagDecl>(D)) { 84 return !TD->isThisDeclarationADefinition(); 85 } else if (auto FD = dyn_cast<FunctionDecl>(D)) { 86 return !FD->isThisDeclarationADefinition(); 87 } else { 88 return false; 89 } 90 } 91 92 template <typename CallbackType> 93 void ForEachMatchingDC( 94 const DeclContext *DC, 95 llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers, 96 CallbackType Callback) { 97 for (const ExternalASTMerger::ImporterPair &IP : Importers) { 98 Source<TranslationUnitDecl *> SourceTU = 99 IP.Forward->getFromContext().getTranslationUnitDecl(); 100 if (auto SourceDC = LookupSameContext(SourceTU, DC, *IP.Reverse)) 101 Callback(IP, SourceDC); 102 } 103 } 104 105 bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) { 106 return llvm::any_of(Decls, [&](const Candidate &D) { 107 return C.first.get()->getKind() == D.first.get()->getKind(); 108 }); 109 } 110 } // end namespace 111 112 ExternalASTMerger::ExternalASTMerger(const ImporterEndpoint &Target, 113 llvm::ArrayRef<ImporterEndpoint> Sources) { 114 for (const ImporterEndpoint &S : Sources) { 115 Importers.push_back( 116 {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM), 117 llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM, 118 /*MinimalImport=*/true)}); 119 } 120 } 121 122 bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, 123 DeclarationName Name) { 124 llvm::SmallVector<NamedDecl *, 1> Decls; 125 llvm::SmallVector<Candidate, 4> CompleteDecls; 126 llvm::SmallVector<Candidate, 4> ForwardDecls; 127 128 auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) { 129 if (IsForwardDeclaration(C.first.get())) { 130 if (!HasDeclOfSameType(ForwardDecls, C)) { 131 ForwardDecls.push_back(C); 132 } 133 } else { 134 CompleteDecls.push_back(C); 135 } 136 }; 137 138 ForEachMatchingDC( 139 DC, Importers, 140 [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) { 141 DeclarationName FromName = IP.Reverse->Import(Name); 142 DeclContextLookupResult Result = SourceDC.get()->lookup(FromName); 143 for (NamedDecl *FromD : Result) { 144 FilterFoundDecl(std::make_pair(FromD, IP.Forward.get())); 145 } 146 }); 147 148 llvm::ArrayRef<Candidate> DeclsToReport = 149 CompleteDecls.empty() ? ForwardDecls : CompleteDecls; 150 151 if (DeclsToReport.empty()) { 152 return false; 153 } 154 155 Decls.reserve(DeclsToReport.size()); 156 for (const Candidate &C : DeclsToReport) { 157 NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get())); 158 assert(d); 159 Decls.push_back(d); 160 } 161 SetExternalVisibleDeclsForName(DC, Name, Decls); 162 return true; 163 } 164 165 void ExternalASTMerger::FindExternalLexicalDecls( 166 const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, 167 SmallVectorImpl<Decl *> &Result) { 168 ForEachMatchingDC( 169 DC, Importers, 170 [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) { 171 for (const Decl *SourceDecl : SourceDC.get()->decls()) { 172 if (IsKindWeWant(SourceDecl->getKind())) { 173 Decl *ImportedDecl = 174 IP.Forward->Import(const_cast<Decl *>(SourceDecl)); 175 assert(ImportedDecl->getDeclContext() == DC); 176 (void)ImportedDecl; 177 } 178 } 179 }); 180 } 181 182 void ExternalASTMerger::CompleteType(TagDecl *Tag) { 183 SmallVector<Decl *, 0> Result; 184 FindExternalLexicalDecls(Tag, [](Decl::Kind) { return true; }, Result); 185 Tag->setHasExternalLexicalStorage(false); 186 } 187