1*0b57cec5SDimitry Andric //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements the ExternalASTMerger, which vends a combination of 10*0b57cec5SDimitry Andric // ASTs from several different ASTContext/FileManager pairs 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 15*0b57cec5SDimitry Andric #include "clang/AST/Decl.h" 16*0b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h" 17*0b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 18*0b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h" 19*0b57cec5SDimitry Andric #include "clang/AST/ExternalASTMerger.h" 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric using namespace clang; 22*0b57cec5SDimitry Andric 23*0b57cec5SDimitry Andric namespace { 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric template <typename T> struct Source { 26*0b57cec5SDimitry Andric T t; 27*0b57cec5SDimitry Andric Source(T t) : t(t) {} 28*0b57cec5SDimitry Andric operator T() { return t; } 29*0b57cec5SDimitry Andric template <typename U = T> U &get() { return t; } 30*0b57cec5SDimitry Andric template <typename U = T> const U &get() const { return t; } 31*0b57cec5SDimitry Andric template <typename U> operator Source<U>() { return Source<U>(t); } 32*0b57cec5SDimitry Andric }; 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate; 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric /// For the given DC, return the DC that is safe to perform lookups on. This is 37*0b57cec5SDimitry Andric /// the DC we actually want to work with most of the time. 38*0b57cec5SDimitry Andric const DeclContext *CanonicalizeDC(const DeclContext *DC) { 39*0b57cec5SDimitry Andric if (isa<LinkageSpecDecl>(DC)) 40*0b57cec5SDimitry Andric return DC->getRedeclContext(); 41*0b57cec5SDimitry Andric return DC; 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric Source<const DeclContext *> 45*0b57cec5SDimitry Andric LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC, 46*0b57cec5SDimitry Andric ASTImporter &ReverseImporter) { 47*0b57cec5SDimitry Andric DC = CanonicalizeDC(DC); 48*0b57cec5SDimitry Andric if (DC->isTranslationUnit()) { 49*0b57cec5SDimitry Andric return SourceTU; 50*0b57cec5SDimitry Andric } 51*0b57cec5SDimitry Andric Source<const DeclContext *> SourceParentDC = 52*0b57cec5SDimitry Andric LookupSameContext(SourceTU, DC->getParent(), ReverseImporter); 53*0b57cec5SDimitry Andric if (!SourceParentDC) { 54*0b57cec5SDimitry Andric // If we couldn't find the parent DC in this TranslationUnit, give up. 55*0b57cec5SDimitry Andric return nullptr; 56*0b57cec5SDimitry Andric } 57*0b57cec5SDimitry Andric auto *ND = cast<NamedDecl>(DC); 58*0b57cec5SDimitry Andric DeclarationName Name = ND->getDeclName(); 59*0b57cec5SDimitry Andric auto SourceNameOrErr = ReverseImporter.Import(Name); 60*0b57cec5SDimitry Andric if (!SourceNameOrErr) { 61*0b57cec5SDimitry Andric llvm::consumeError(SourceNameOrErr.takeError()); 62*0b57cec5SDimitry Andric return nullptr; 63*0b57cec5SDimitry Andric } 64*0b57cec5SDimitry Andric Source<DeclarationName> SourceName = *SourceNameOrErr; 65*0b57cec5SDimitry Andric DeclContext::lookup_result SearchResult = 66*0b57cec5SDimitry Andric SourceParentDC.get()->lookup(SourceName.get()); 67*0b57cec5SDimitry Andric size_t SearchResultSize = SearchResult.size(); 68*0b57cec5SDimitry Andric if (SearchResultSize == 0 || SearchResultSize > 1) { 69*0b57cec5SDimitry Andric // There are two cases here. First, we might not find the name. 70*0b57cec5SDimitry Andric // We might also find multiple copies, in which case we have no 71*0b57cec5SDimitry Andric // guarantee that the one we wanted is the one we pick. (E.g., 72*0b57cec5SDimitry Andric // if we have two specializations of the same template it is 73*0b57cec5SDimitry Andric // very hard to determine which is the one you want.) 74*0b57cec5SDimitry Andric // 75*0b57cec5SDimitry Andric // The Origins map fixes this problem by allowing the origin to be 76*0b57cec5SDimitry Andric // explicitly recorded, so we trigger that recording by returning 77*0b57cec5SDimitry Andric // nothing (rather than a possibly-inaccurate guess) here. 78*0b57cec5SDimitry Andric return nullptr; 79*0b57cec5SDimitry Andric } else { 80*0b57cec5SDimitry Andric NamedDecl *SearchResultDecl = SearchResult[0]; 81*0b57cec5SDimitry Andric if (isa<DeclContext>(SearchResultDecl) && 82*0b57cec5SDimitry Andric SearchResultDecl->getKind() == DC->getDeclKind()) 83*0b57cec5SDimitry Andric return cast<DeclContext>(SearchResultDecl)->getPrimaryContext(); 84*0b57cec5SDimitry Andric return nullptr; // This type of lookup is unsupported 85*0b57cec5SDimitry Andric } 86*0b57cec5SDimitry Andric } 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric /// A custom implementation of ASTImporter, for ExternalASTMerger's purposes. 89*0b57cec5SDimitry Andric /// 90*0b57cec5SDimitry Andric /// There are several modifications: 91*0b57cec5SDimitry Andric /// 92*0b57cec5SDimitry Andric /// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few 93*0b57cec5SDimitry Andric /// others), which instructs Clang to refer to ExternalASTMerger. Also, it 94*0b57cec5SDimitry Andric /// forces MinimalImport to true, which is necessary to make this work. 95*0b57cec5SDimitry Andric /// - It maintains a reverse importer for use with names. This allows lookup of 96*0b57cec5SDimitry Andric /// arbitrary names in the source context. 97*0b57cec5SDimitry Andric /// - It updates the ExternalASTMerger's origin map as needed whenever a 98*0b57cec5SDimitry Andric /// it sees a DeclContext. 99*0b57cec5SDimitry Andric class LazyASTImporter : public ASTImporter { 100*0b57cec5SDimitry Andric private: 101*0b57cec5SDimitry Andric ExternalASTMerger &Parent; 102*0b57cec5SDimitry Andric ASTImporter Reverse; 103*0b57cec5SDimitry Andric const ExternalASTMerger::OriginMap &FromOrigins; 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric llvm::raw_ostream &logs() { return Parent.logs(); } 106*0b57cec5SDimitry Andric public: 107*0b57cec5SDimitry Andric LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext, 108*0b57cec5SDimitry Andric FileManager &ToFileManager, ASTContext &FromContext, 109*0b57cec5SDimitry Andric FileManager &FromFileManager, 110*0b57cec5SDimitry Andric const ExternalASTMerger::OriginMap &_FromOrigins) 111*0b57cec5SDimitry Andric : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager, 112*0b57cec5SDimitry Andric /*MinimalImport=*/true), 113*0b57cec5SDimitry Andric Parent(_Parent), Reverse(FromContext, FromFileManager, ToContext, 114*0b57cec5SDimitry Andric ToFileManager, /*MinimalImport=*/true), FromOrigins(_FromOrigins) {} 115*0b57cec5SDimitry Andric 116*0b57cec5SDimitry Andric /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin 117*0b57cec5SDimitry Andric /// map is kept up to date. Also set the appropriate flags. 118*0b57cec5SDimitry Andric void Imported(Decl *From, Decl *To) override { 119*0b57cec5SDimitry Andric if (auto *ToDC = dyn_cast<DeclContext>(To)) { 120*0b57cec5SDimitry Andric const bool LoggingEnabled = Parent.LoggingEnabled(); 121*0b57cec5SDimitry Andric if (LoggingEnabled) 122*0b57cec5SDimitry Andric logs() << "(ExternalASTMerger*)" << (void*)&Parent 123*0b57cec5SDimitry Andric << " imported (DeclContext*)" << (void*)ToDC 124*0b57cec5SDimitry Andric << ", (ASTContext*)" << (void*)&getToContext() 125*0b57cec5SDimitry Andric << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From) 126*0b57cec5SDimitry Andric << ", (ASTContext*)" << (void*)&getFromContext() 127*0b57cec5SDimitry Andric << "\n"; 128*0b57cec5SDimitry Andric Source<DeclContext *> FromDC( 129*0b57cec5SDimitry Andric cast<DeclContext>(From)->getPrimaryContext()); 130*0b57cec5SDimitry Andric if (FromOrigins.count(FromDC) && 131*0b57cec5SDimitry Andric Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) { 132*0b57cec5SDimitry Andric if (LoggingEnabled) 133*0b57cec5SDimitry Andric logs() << "(ExternalASTMerger*)" << (void*)&Parent 134*0b57cec5SDimitry Andric << " forced origin (DeclContext*)" 135*0b57cec5SDimitry Andric << (void*)FromOrigins.at(FromDC).DC 136*0b57cec5SDimitry Andric << ", (ASTContext*)" 137*0b57cec5SDimitry Andric << (void*)FromOrigins.at(FromDC).AST 138*0b57cec5SDimitry Andric << "\n"; 139*0b57cec5SDimitry Andric Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC)); 140*0b57cec5SDimitry Andric } else { 141*0b57cec5SDimitry Andric if (LoggingEnabled) 142*0b57cec5SDimitry Andric logs() << "(ExternalASTMerger*)" << (void*)&Parent 143*0b57cec5SDimitry Andric << " maybe recording origin (DeclContext*)" << (void*)FromDC 144*0b57cec5SDimitry Andric << ", (ASTContext*)" << (void*)&getFromContext() 145*0b57cec5SDimitry Andric << "\n"; 146*0b57cec5SDimitry Andric Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()}); 147*0b57cec5SDimitry Andric } 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric if (auto *ToTag = dyn_cast<TagDecl>(To)) { 150*0b57cec5SDimitry Andric ToTag->setHasExternalLexicalStorage(); 151*0b57cec5SDimitry Andric ToTag->getPrimaryContext()->setMustBuildLookupTable(); 152*0b57cec5SDimitry Andric assert(Parent.CanComplete(ToTag)); 153*0b57cec5SDimitry Andric } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) { 154*0b57cec5SDimitry Andric ToNamespace->setHasExternalVisibleStorage(); 155*0b57cec5SDimitry Andric assert(Parent.CanComplete(ToNamespace)); 156*0b57cec5SDimitry Andric } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) { 157*0b57cec5SDimitry Andric ToContainer->setHasExternalLexicalStorage(); 158*0b57cec5SDimitry Andric ToContainer->getPrimaryContext()->setMustBuildLookupTable(); 159*0b57cec5SDimitry Andric assert(Parent.CanComplete(ToContainer)); 160*0b57cec5SDimitry Andric } 161*0b57cec5SDimitry Andric } 162*0b57cec5SDimitry Andric ASTImporter &GetReverse() { return Reverse; } 163*0b57cec5SDimitry Andric }; 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) { 166*0b57cec5SDimitry Andric if (isa<FunctionDecl>(C.first.get())) 167*0b57cec5SDimitry Andric return false; 168*0b57cec5SDimitry Andric return llvm::any_of(Decls, [&](const Candidate &D) { 169*0b57cec5SDimitry Andric return C.first.get()->getKind() == D.first.get()->getKind(); 170*0b57cec5SDimitry Andric }); 171*0b57cec5SDimitry Andric } 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric } // end namespace 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) { 176*0b57cec5SDimitry Andric for (const std::unique_ptr<ASTImporter> &I : Importers) 177*0b57cec5SDimitry Andric if (&I->getFromContext() == &OriginContext) 178*0b57cec5SDimitry Andric return *I; 179*0b57cec5SDimitry Andric llvm_unreachable("We should have an importer for this origin!"); 180*0b57cec5SDimitry Andric } 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric namespace { 183*0b57cec5SDimitry Andric LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger, 184*0b57cec5SDimitry Andric ASTContext &OriginContext) { 185*0b57cec5SDimitry Andric return static_cast<LazyASTImporter &>( 186*0b57cec5SDimitry Andric Merger.ImporterForOrigin(OriginContext)); 187*0b57cec5SDimitry Andric } 188*0b57cec5SDimitry Andric } 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) { 191*0b57cec5SDimitry Andric for (const std::unique_ptr<ASTImporter> &I : Importers) 192*0b57cec5SDimitry Andric if (&I->getFromContext() == &OriginContext) 193*0b57cec5SDimitry Andric return true; 194*0b57cec5SDimitry Andric return false; 195*0b57cec5SDimitry Andric } 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric template <typename CallbackType> 198*0b57cec5SDimitry Andric void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC, 199*0b57cec5SDimitry Andric CallbackType Callback) { 200*0b57cec5SDimitry Andric if (Origins.count(DC)) { 201*0b57cec5SDimitry Andric ExternalASTMerger::DCOrigin Origin = Origins[DC]; 202*0b57cec5SDimitry Andric LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); 203*0b57cec5SDimitry Andric Callback(Importer, Importer.GetReverse(), Origin.DC); 204*0b57cec5SDimitry Andric } else { 205*0b57cec5SDimitry Andric bool DidCallback = false; 206*0b57cec5SDimitry Andric for (const std::unique_ptr<ASTImporter> &Importer : Importers) { 207*0b57cec5SDimitry Andric Source<TranslationUnitDecl *> SourceTU = 208*0b57cec5SDimitry Andric Importer->getFromContext().getTranslationUnitDecl(); 209*0b57cec5SDimitry Andric ASTImporter &Reverse = 210*0b57cec5SDimitry Andric static_cast<LazyASTImporter *>(Importer.get())->GetReverse(); 211*0b57cec5SDimitry Andric if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) { 212*0b57cec5SDimitry Andric DidCallback = true; 213*0b57cec5SDimitry Andric if (Callback(*Importer, Reverse, SourceDC)) 214*0b57cec5SDimitry Andric break; 215*0b57cec5SDimitry Andric } 216*0b57cec5SDimitry Andric } 217*0b57cec5SDimitry Andric if (!DidCallback && LoggingEnabled()) 218*0b57cec5SDimitry Andric logs() << "(ExternalASTMerger*)" << (void*)this 219*0b57cec5SDimitry Andric << " asserting for (DeclContext*)" << (const void*)DC 220*0b57cec5SDimitry Andric << ", (ASTContext*)" << (void*)&Target.AST 221*0b57cec5SDimitry Andric << "\n"; 222*0b57cec5SDimitry Andric assert(DidCallback && "Couldn't find a source context matching our DC"); 223*0b57cec5SDimitry Andric } 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric void ExternalASTMerger::CompleteType(TagDecl *Tag) { 227*0b57cec5SDimitry Andric assert(Tag->hasExternalLexicalStorage()); 228*0b57cec5SDimitry Andric ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse, 229*0b57cec5SDimitry Andric Source<const DeclContext *> SourceDC) -> bool { 230*0b57cec5SDimitry Andric auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get())); 231*0b57cec5SDimitry Andric if (SourceTag->hasExternalLexicalStorage()) 232*0b57cec5SDimitry Andric SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag); 233*0b57cec5SDimitry Andric if (!SourceTag->getDefinition()) 234*0b57cec5SDimitry Andric return false; 235*0b57cec5SDimitry Andric Forward.MapImported(SourceTag, Tag); 236*0b57cec5SDimitry Andric if (llvm::Error Err = Forward.ImportDefinition(SourceTag)) 237*0b57cec5SDimitry Andric llvm::consumeError(std::move(Err)); 238*0b57cec5SDimitry Andric Tag->setCompleteDefinition(SourceTag->isCompleteDefinition()); 239*0b57cec5SDimitry Andric return true; 240*0b57cec5SDimitry Andric }); 241*0b57cec5SDimitry Andric } 242*0b57cec5SDimitry Andric 243*0b57cec5SDimitry Andric void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) { 244*0b57cec5SDimitry Andric assert(Interface->hasExternalLexicalStorage()); 245*0b57cec5SDimitry Andric ForEachMatchingDC( 246*0b57cec5SDimitry Andric Interface, [&](ASTImporter &Forward, ASTImporter &Reverse, 247*0b57cec5SDimitry Andric Source<const DeclContext *> SourceDC) -> bool { 248*0b57cec5SDimitry Andric auto *SourceInterface = const_cast<ObjCInterfaceDecl *>( 249*0b57cec5SDimitry Andric cast<ObjCInterfaceDecl>(SourceDC.get())); 250*0b57cec5SDimitry Andric if (SourceInterface->hasExternalLexicalStorage()) 251*0b57cec5SDimitry Andric SourceInterface->getASTContext().getExternalSource()->CompleteType( 252*0b57cec5SDimitry Andric SourceInterface); 253*0b57cec5SDimitry Andric if (!SourceInterface->getDefinition()) 254*0b57cec5SDimitry Andric return false; 255*0b57cec5SDimitry Andric Forward.MapImported(SourceInterface, Interface); 256*0b57cec5SDimitry Andric if (llvm::Error Err = Forward.ImportDefinition(SourceInterface)) 257*0b57cec5SDimitry Andric llvm::consumeError(std::move(Err)); 258*0b57cec5SDimitry Andric return true; 259*0b57cec5SDimitry Andric }); 260*0b57cec5SDimitry Andric } 261*0b57cec5SDimitry Andric 262*0b57cec5SDimitry Andric bool ExternalASTMerger::CanComplete(DeclContext *Interface) { 263*0b57cec5SDimitry Andric assert(Interface->hasExternalLexicalStorage() || 264*0b57cec5SDimitry Andric Interface->hasExternalVisibleStorage()); 265*0b57cec5SDimitry Andric bool FoundMatchingDC = false; 266*0b57cec5SDimitry Andric ForEachMatchingDC(Interface, 267*0b57cec5SDimitry Andric [&](ASTImporter &Forward, ASTImporter &Reverse, 268*0b57cec5SDimitry Andric Source<const DeclContext *> SourceDC) -> bool { 269*0b57cec5SDimitry Andric FoundMatchingDC = true; 270*0b57cec5SDimitry Andric return true; 271*0b57cec5SDimitry Andric }); 272*0b57cec5SDimitry Andric return FoundMatchingDC; 273*0b57cec5SDimitry Andric } 274*0b57cec5SDimitry Andric 275*0b57cec5SDimitry Andric namespace { 276*0b57cec5SDimitry Andric bool IsSameDC(const DeclContext *D1, const DeclContext *D2) { 277*0b57cec5SDimitry Andric if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2)) 278*0b57cec5SDimitry Andric return true; // There are many cases where Objective-C is ambiguous. 279*0b57cec5SDimitry Andric if (auto *T1 = dyn_cast<TagDecl>(D1)) 280*0b57cec5SDimitry Andric if (auto *T2 = dyn_cast<TagDecl>(D2)) 281*0b57cec5SDimitry Andric if (T1->getFirstDecl() == T2->getFirstDecl()) 282*0b57cec5SDimitry Andric return true; 283*0b57cec5SDimitry Andric return D1 == D2 || D1 == CanonicalizeDC(D2); 284*0b57cec5SDimitry Andric } 285*0b57cec5SDimitry Andric } 286*0b57cec5SDimitry Andric 287*0b57cec5SDimitry Andric void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC, 288*0b57cec5SDimitry Andric DCOrigin Origin) { 289*0b57cec5SDimitry Andric LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST); 290*0b57cec5SDimitry Andric ASTImporter &Reverse = Importer.GetReverse(); 291*0b57cec5SDimitry Andric Source<const DeclContext *> FoundFromDC = 292*0b57cec5SDimitry Andric LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse); 293*0b57cec5SDimitry Andric const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC); 294*0b57cec5SDimitry Andric if (DoRecord) 295*0b57cec5SDimitry Andric RecordOriginImpl(ToDC, Origin, Importer); 296*0b57cec5SDimitry Andric if (LoggingEnabled()) 297*0b57cec5SDimitry Andric logs() << "(ExternalASTMerger*)" << (void*)this 298*0b57cec5SDimitry Andric << (DoRecord ? " decided " : " decided NOT") 299*0b57cec5SDimitry Andric << " to record origin (DeclContext*)" << (void*)Origin.DC 300*0b57cec5SDimitry Andric << ", (ASTContext*)" << (void*)&Origin.AST 301*0b57cec5SDimitry Andric << "\n"; 302*0b57cec5SDimitry Andric } 303*0b57cec5SDimitry Andric 304*0b57cec5SDimitry Andric void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC, 305*0b57cec5SDimitry Andric DCOrigin Origin) { 306*0b57cec5SDimitry Andric RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST)); 307*0b57cec5SDimitry Andric } 308*0b57cec5SDimitry Andric 309*0b57cec5SDimitry Andric void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, 310*0b57cec5SDimitry Andric ASTImporter &Importer) { 311*0b57cec5SDimitry Andric Origins[ToDC] = Origin; 312*0b57cec5SDimitry Andric Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC))); 313*0b57cec5SDimitry Andric } 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target, 316*0b57cec5SDimitry Andric llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) { 317*0b57cec5SDimitry Andric AddSources(Sources); 318*0b57cec5SDimitry Andric } 319*0b57cec5SDimitry Andric 320*0b57cec5SDimitry Andric void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) { 321*0b57cec5SDimitry Andric for (const ImporterSource &S : Sources) { 322*0b57cec5SDimitry Andric assert(&S.AST != &Target.AST); 323*0b57cec5SDimitry Andric Importers.push_back(llvm::make_unique<LazyASTImporter>( 324*0b57cec5SDimitry Andric *this, Target.AST, Target.FM, S.AST, S.FM, S.OM)); 325*0b57cec5SDimitry Andric } 326*0b57cec5SDimitry Andric } 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) { 329*0b57cec5SDimitry Andric if (LoggingEnabled()) 330*0b57cec5SDimitry Andric for (const ImporterSource &S : Sources) 331*0b57cec5SDimitry Andric logs() << "(ExternalASTMerger*)" << (void*)this 332*0b57cec5SDimitry Andric << " removing source (ASTContext*)" << (void*)&S.AST 333*0b57cec5SDimitry Andric << "\n"; 334*0b57cec5SDimitry Andric Importers.erase( 335*0b57cec5SDimitry Andric std::remove_if(Importers.begin(), Importers.end(), 336*0b57cec5SDimitry Andric [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool { 337*0b57cec5SDimitry Andric for (const ImporterSource &S : Sources) { 338*0b57cec5SDimitry Andric if (&Importer->getFromContext() == &S.AST) 339*0b57cec5SDimitry Andric return true; 340*0b57cec5SDimitry Andric } 341*0b57cec5SDimitry Andric return false; 342*0b57cec5SDimitry Andric }), 343*0b57cec5SDimitry Andric Importers.end()); 344*0b57cec5SDimitry Andric for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) { 345*0b57cec5SDimitry Andric std::pair<const DeclContext *, DCOrigin> Origin = *OI; 346*0b57cec5SDimitry Andric bool Erase = false; 347*0b57cec5SDimitry Andric for (const ImporterSource &S : Sources) { 348*0b57cec5SDimitry Andric if (&S.AST == Origin.second.AST) { 349*0b57cec5SDimitry Andric Erase = true; 350*0b57cec5SDimitry Andric break; 351*0b57cec5SDimitry Andric } 352*0b57cec5SDimitry Andric } 353*0b57cec5SDimitry Andric if (Erase) 354*0b57cec5SDimitry Andric OI = Origins.erase(OI); 355*0b57cec5SDimitry Andric else 356*0b57cec5SDimitry Andric ++OI; 357*0b57cec5SDimitry Andric } 358*0b57cec5SDimitry Andric } 359*0b57cec5SDimitry Andric 360*0b57cec5SDimitry Andric template <typename DeclTy> 361*0b57cec5SDimitry Andric static bool importSpecializations(DeclTy *D, ASTImporter *Importer) { 362*0b57cec5SDimitry Andric for (auto *Spec : D->specializations()) { 363*0b57cec5SDimitry Andric auto ImportedSpecOrError = Importer->Import(Spec); 364*0b57cec5SDimitry Andric if (!ImportedSpecOrError) { 365*0b57cec5SDimitry Andric llvm::consumeError(ImportedSpecOrError.takeError()); 366*0b57cec5SDimitry Andric return true; 367*0b57cec5SDimitry Andric } 368*0b57cec5SDimitry Andric } 369*0b57cec5SDimitry Andric return false; 370*0b57cec5SDimitry Andric } 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric /// Imports specializations from template declarations that can be specialized. 373*0b57cec5SDimitry Andric static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) { 374*0b57cec5SDimitry Andric if (!isa<TemplateDecl>(D)) 375*0b57cec5SDimitry Andric return false; 376*0b57cec5SDimitry Andric if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D)) 377*0b57cec5SDimitry Andric return importSpecializations(FunctionTD, Importer); 378*0b57cec5SDimitry Andric else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D)) 379*0b57cec5SDimitry Andric return importSpecializations(ClassTD, Importer); 380*0b57cec5SDimitry Andric else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D)) 381*0b57cec5SDimitry Andric return importSpecializations(VarTD, Importer); 382*0b57cec5SDimitry Andric return false; 383*0b57cec5SDimitry Andric } 384*0b57cec5SDimitry Andric 385*0b57cec5SDimitry Andric bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC, 386*0b57cec5SDimitry Andric DeclarationName Name) { 387*0b57cec5SDimitry Andric llvm::SmallVector<NamedDecl *, 1> Decls; 388*0b57cec5SDimitry Andric llvm::SmallVector<Candidate, 4> Candidates; 389*0b57cec5SDimitry Andric 390*0b57cec5SDimitry Andric auto FilterFoundDecl = [&Candidates](const Candidate &C) { 391*0b57cec5SDimitry Andric if (!HasDeclOfSameType(Candidates, C)) 392*0b57cec5SDimitry Andric Candidates.push_back(C); 393*0b57cec5SDimitry Andric }; 394*0b57cec5SDimitry Andric 395*0b57cec5SDimitry Andric ForEachMatchingDC(DC, 396*0b57cec5SDimitry Andric [&](ASTImporter &Forward, ASTImporter &Reverse, 397*0b57cec5SDimitry Andric Source<const DeclContext *> SourceDC) -> bool { 398*0b57cec5SDimitry Andric auto FromNameOrErr = Reverse.Import(Name); 399*0b57cec5SDimitry Andric if (!FromNameOrErr) { 400*0b57cec5SDimitry Andric llvm::consumeError(FromNameOrErr.takeError()); 401*0b57cec5SDimitry Andric return false; 402*0b57cec5SDimitry Andric } 403*0b57cec5SDimitry Andric DeclContextLookupResult Result = 404*0b57cec5SDimitry Andric SourceDC.get()->lookup(*FromNameOrErr); 405*0b57cec5SDimitry Andric for (NamedDecl *FromD : Result) { 406*0b57cec5SDimitry Andric FilterFoundDecl(std::make_pair(FromD, &Forward)); 407*0b57cec5SDimitry Andric } 408*0b57cec5SDimitry Andric return false; 409*0b57cec5SDimitry Andric }); 410*0b57cec5SDimitry Andric 411*0b57cec5SDimitry Andric if (Candidates.empty()) 412*0b57cec5SDimitry Andric return false; 413*0b57cec5SDimitry Andric 414*0b57cec5SDimitry Andric Decls.reserve(Candidates.size()); 415*0b57cec5SDimitry Andric for (const Candidate &C : Candidates) { 416*0b57cec5SDimitry Andric Decl *LookupRes = C.first.get(); 417*0b57cec5SDimitry Andric ASTImporter *Importer = C.second; 418*0b57cec5SDimitry Andric auto NDOrErr = Importer->Import(LookupRes); 419*0b57cec5SDimitry Andric assert(NDOrErr); 420*0b57cec5SDimitry Andric (void)static_cast<bool>(NDOrErr); 421*0b57cec5SDimitry Andric NamedDecl *ND = cast_or_null<NamedDecl>(*NDOrErr); 422*0b57cec5SDimitry Andric assert(ND); 423*0b57cec5SDimitry Andric // If we don't import specialization, they are not available via lookup 424*0b57cec5SDimitry Andric // because the lookup result is imported TemplateDecl and it does not 425*0b57cec5SDimitry Andric // reference its specializations until they are imported explicitly. 426*0b57cec5SDimitry Andric bool IsSpecImportFailed = 427*0b57cec5SDimitry Andric importSpecializationsIfNeeded(LookupRes, Importer); 428*0b57cec5SDimitry Andric assert(!IsSpecImportFailed); 429*0b57cec5SDimitry Andric (void)IsSpecImportFailed; 430*0b57cec5SDimitry Andric Decls.push_back(ND); 431*0b57cec5SDimitry Andric } 432*0b57cec5SDimitry Andric SetExternalVisibleDeclsForName(DC, Name, Decls); 433*0b57cec5SDimitry Andric return true; 434*0b57cec5SDimitry Andric } 435*0b57cec5SDimitry Andric 436*0b57cec5SDimitry Andric void ExternalASTMerger::FindExternalLexicalDecls( 437*0b57cec5SDimitry Andric const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, 438*0b57cec5SDimitry Andric SmallVectorImpl<Decl *> &Result) { 439*0b57cec5SDimitry Andric ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse, 440*0b57cec5SDimitry Andric Source<const DeclContext *> SourceDC) -> bool { 441*0b57cec5SDimitry Andric for (const Decl *SourceDecl : SourceDC.get()->decls()) { 442*0b57cec5SDimitry Andric if (IsKindWeWant(SourceDecl->getKind())) { 443*0b57cec5SDimitry Andric auto ImportedDeclOrErr = Forward.Import(SourceDecl); 444*0b57cec5SDimitry Andric if (ImportedDeclOrErr) 445*0b57cec5SDimitry Andric assert(!(*ImportedDeclOrErr) || 446*0b57cec5SDimitry Andric IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC)); 447*0b57cec5SDimitry Andric else 448*0b57cec5SDimitry Andric llvm::consumeError(ImportedDeclOrErr.takeError()); 449*0b57cec5SDimitry Andric } 450*0b57cec5SDimitry Andric } 451*0b57cec5SDimitry Andric return false; 452*0b57cec5SDimitry Andric }); 453*0b57cec5SDimitry Andric } 454*0b57cec5SDimitry Andric 455