1718292f2SDouglas Gregor //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===// 2718292f2SDouglas Gregor // 3718292f2SDouglas Gregor // The LLVM Compiler Infrastructure 4718292f2SDouglas Gregor // 5718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source 6718292f2SDouglas Gregor // License. See LICENSE.TXT for details. 7718292f2SDouglas Gregor // 8718292f2SDouglas Gregor //===----------------------------------------------------------------------===// 9718292f2SDouglas Gregor // 10718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout 11718292f2SDouglas Gregor // of a module as it relates to headers. 12718292f2SDouglas Gregor // 13718292f2SDouglas Gregor //===----------------------------------------------------------------------===// 14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h" 15718292f2SDouglas Gregor #include "clang/Lex/Lexer.h" 16718292f2SDouglas Gregor #include "clang/Lex/LiteralSupport.h" 17718292f2SDouglas Gregor #include "clang/Lex/LexDiagnostic.h" 18718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h" 19718292f2SDouglas Gregor #include "clang/Basic/FileManager.h" 20718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h" 21718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h" 22718292f2SDouglas Gregor #include "llvm/Support/Allocator.h" 23e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h" 24718292f2SDouglas Gregor #include "llvm/Support/Host.h" 255257fc63SDouglas Gregor #include "llvm/Support/PathV2.h" 26718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 27718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h" 28718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h" 29*07c22b78SDouglas Gregor #include <stdlib.h> 30718292f2SDouglas Gregor using namespace clang; 31718292f2SDouglas Gregor 322b82c2a5SDouglas Gregor Module::ExportDecl 332b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 342b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 352b82c2a5SDouglas Gregor bool Complain) { 36f5eedd05SDouglas Gregor // We may have just a wildcard. 37f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 38f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 39f5eedd05SDouglas Gregor return Module::ExportDecl(0, true); 40f5eedd05SDouglas Gregor } 41f5eedd05SDouglas Gregor 422b82c2a5SDouglas Gregor // Find the starting module. 432b82c2a5SDouglas Gregor Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod); 442b82c2a5SDouglas Gregor if (!Context) { 452b82c2a5SDouglas Gregor if (Complain) 462b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[0].second, 472b82c2a5SDouglas Gregor diag::err_mmap_missing_module_unqualified) 482b82c2a5SDouglas Gregor << Unresolved.Id[0].first << Mod->getFullModuleName(); 492b82c2a5SDouglas Gregor 502b82c2a5SDouglas Gregor return Module::ExportDecl(); 512b82c2a5SDouglas Gregor } 522b82c2a5SDouglas Gregor 532b82c2a5SDouglas Gregor // Dig into the module path. 542b82c2a5SDouglas Gregor for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) { 552b82c2a5SDouglas Gregor Module *Sub = lookupModuleQualified(Unresolved.Id[I].first, 562b82c2a5SDouglas Gregor Context); 572b82c2a5SDouglas Gregor if (!Sub) { 582b82c2a5SDouglas Gregor if (Complain) 592b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[I].second, 602b82c2a5SDouglas Gregor diag::err_mmap_missing_module_qualified) 612b82c2a5SDouglas Gregor << Unresolved.Id[I].first << Context->getFullModuleName() 622b82c2a5SDouglas Gregor << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second); 632b82c2a5SDouglas Gregor 642b82c2a5SDouglas Gregor return Module::ExportDecl(); 652b82c2a5SDouglas Gregor } 662b82c2a5SDouglas Gregor 672b82c2a5SDouglas Gregor Context = Sub; 682b82c2a5SDouglas Gregor } 692b82c2a5SDouglas Gregor 702b82c2a5SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 712b82c2a5SDouglas Gregor } 722b82c2a5SDouglas Gregor 731fb5c3a6SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, 7489929282SDouglas Gregor const LangOptions &LangOpts, const TargetInfo *Target) 753ec6663bSDouglas Gregor : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0) 761fb5c3a6SDouglas Gregor { 77c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 78c95d8192SDylan Noblesmith Diags = IntrusiveRefCntPtr<DiagnosticsEngine>( 79718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 80718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 81718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 82718292f2SDouglas Gregor } 83718292f2SDouglas Gregor 84718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 855acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 865acdf59eSDouglas Gregor IEnd = Modules.end(); 875acdf59eSDouglas Gregor I != IEnd; ++I) { 885acdf59eSDouglas Gregor delete I->getValue(); 895acdf59eSDouglas Gregor } 905acdf59eSDouglas Gregor 91718292f2SDouglas Gregor delete SourceMgr; 92718292f2SDouglas Gregor } 93718292f2SDouglas Gregor 9489929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 9589929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 9689929282SDouglas Gregor "Improper target override"); 9789929282SDouglas Gregor this->Target = &Target; 9889929282SDouglas Gregor } 9989929282SDouglas Gregor 100de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 101ab0c8a84SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 102ab0c8a84SDouglas Gregor = Headers.find(File); 1031fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 1041fb5c3a6SDouglas Gregor // If a header corresponds to an unavailable module, don't report 1051fb5c3a6SDouglas Gregor // that it maps to anything. 1061fb5c3a6SDouglas Gregor if (!Known->second->isAvailable()) 1071fb5c3a6SDouglas Gregor return 0; 1081fb5c3a6SDouglas Gregor 109ab0c8a84SDouglas Gregor return Known->second; 1101fb5c3a6SDouglas Gregor } 111ab0c8a84SDouglas Gregor 112b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 113b65dbfffSDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 114b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 115a89c5ac4SDouglas Gregor 116a89c5ac4SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 117a89c5ac4SDouglas Gregor // an umbrella header. 118b65dbfffSDouglas Gregor do { 119a89c5ac4SDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 120a89c5ac4SDouglas Gregor = UmbrellaDirs.find(Dir); 121a89c5ac4SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 122a89c5ac4SDouglas Gregor Module *Result = KnownDir->second; 123930a85ccSDouglas Gregor 124930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 12573141fa9SDouglas Gregor // directory. 126930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 12773141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 128930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 129930a85ccSDouglas Gregor 130930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 131a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 132a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 133a89c5ac4SDouglas Gregor // the actual header is located. 1349458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 1359458f82dSDouglas Gregor 1367033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 137a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 138a89c5ac4SDouglas Gregor StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName()); 139a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 1409458f82dSDouglas Gregor Explicit).first; 141a89c5ac4SDouglas Gregor 142a89c5ac4SDouglas Gregor // Associate the module and the directory. 143a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 144a89c5ac4SDouglas Gregor 145a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 146a89c5ac4SDouglas Gregor // wildcard to the set of exports. 147930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 148a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 149a89c5ac4SDouglas Gregor } 150a89c5ac4SDouglas Gregor 151a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 152a89c5ac4SDouglas Gregor StringRef Name = llvm::sys::path::stem(File->getName()); 153a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 1549458f82dSDouglas Gregor Explicit).first; 155a89c5ac4SDouglas Gregor 156a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 157a89c5ac4SDouglas Gregor // wildcard to the set of exports. 158930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 159a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 160a89c5ac4SDouglas Gregor } else { 161a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 162a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 163a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 164a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 165a89c5ac4SDouglas Gregor } 166a89c5ac4SDouglas Gregor 167a89c5ac4SDouglas Gregor Headers[File] = Result; 1681fb5c3a6SDouglas Gregor 1691fb5c3a6SDouglas Gregor // If a header corresponds to an unavailable module, don't report 1701fb5c3a6SDouglas Gregor // that it maps to anything. 1711fb5c3a6SDouglas Gregor if (!Result->isAvailable()) 1721fb5c3a6SDouglas Gregor return 0; 1731fb5c3a6SDouglas Gregor 174a89c5ac4SDouglas Gregor return Result; 175a89c5ac4SDouglas Gregor } 176a89c5ac4SDouglas Gregor 177a89c5ac4SDouglas Gregor SkippedDirs.push_back(Dir); 178a89c5ac4SDouglas Gregor 179b65dbfffSDouglas Gregor // Retrieve our parent path. 180b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 181b65dbfffSDouglas Gregor if (DirName.empty()) 182b65dbfffSDouglas Gregor break; 183b65dbfffSDouglas Gregor 184b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 185b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 186a89c5ac4SDouglas Gregor } while (Dir); 187b65dbfffSDouglas Gregor 188ab0c8a84SDouglas Gregor return 0; 189ab0c8a84SDouglas Gregor } 190ab0c8a84SDouglas Gregor 1911fb5c3a6SDouglas Gregor bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) { 1921fb5c3a6SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 1931fb5c3a6SDouglas Gregor = Headers.find(Header); 1941fb5c3a6SDouglas Gregor if (Known != Headers.end()) 1951fb5c3a6SDouglas Gregor return !Known->second->isAvailable(); 1961fb5c3a6SDouglas Gregor 1971fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 1981fb5c3a6SDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 1991fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 2001fb5c3a6SDouglas Gregor 2011fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 2021fb5c3a6SDouglas Gregor // an umbrella header. 2031fb5c3a6SDouglas Gregor do { 2041fb5c3a6SDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 2051fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 2061fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 2071fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 2081fb5c3a6SDouglas Gregor if (!Found->isAvailable()) 2091fb5c3a6SDouglas Gregor return true; 2101fb5c3a6SDouglas Gregor 2111fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 2121fb5c3a6SDouglas Gregor // directory. 2131fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 2141fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 2151fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 2161fb5c3a6SDouglas Gregor 2171fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 2181fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 2191fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 2201fb5c3a6SDouglas Gregor StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName()); 2211fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 2221fb5c3a6SDouglas Gregor if (!Found) 2231fb5c3a6SDouglas Gregor return false; 2241fb5c3a6SDouglas Gregor if (!Found->isAvailable()) 2251fb5c3a6SDouglas Gregor return true; 2261fb5c3a6SDouglas Gregor } 2271fb5c3a6SDouglas Gregor 2281fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 2291fb5c3a6SDouglas Gregor StringRef Name = llvm::sys::path::stem(Header->getName()); 2301fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 2311fb5c3a6SDouglas Gregor if (!Found) 2321fb5c3a6SDouglas Gregor return false; 2331fb5c3a6SDouglas Gregor } 2341fb5c3a6SDouglas Gregor 2351fb5c3a6SDouglas Gregor return !Found->isAvailable(); 2361fb5c3a6SDouglas Gregor } 2371fb5c3a6SDouglas Gregor 2381fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 2391fb5c3a6SDouglas Gregor 2401fb5c3a6SDouglas Gregor // Retrieve our parent path. 2411fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 2421fb5c3a6SDouglas Gregor if (DirName.empty()) 2431fb5c3a6SDouglas Gregor break; 2441fb5c3a6SDouglas Gregor 2451fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 2461fb5c3a6SDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 2471fb5c3a6SDouglas Gregor } while (Dir); 2481fb5c3a6SDouglas Gregor 2491fb5c3a6SDouglas Gregor return false; 2501fb5c3a6SDouglas Gregor } 2511fb5c3a6SDouglas Gregor 252de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) { 25388bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 25488bdfb0eSDouglas Gregor if (Known != Modules.end()) 25588bdfb0eSDouglas Gregor return Known->getValue(); 25688bdfb0eSDouglas Gregor 25788bdfb0eSDouglas Gregor return 0; 25888bdfb0eSDouglas Gregor } 25988bdfb0eSDouglas Gregor 2602b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) { 2612b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 2622b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 2632b82c2a5SDouglas Gregor return Sub; 2642b82c2a5SDouglas Gregor } 2652b82c2a5SDouglas Gregor 2662b82c2a5SDouglas Gregor return findModule(Name); 2672b82c2a5SDouglas Gregor } 2682b82c2a5SDouglas Gregor 2692b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) { 2702b82c2a5SDouglas Gregor if (!Context) 2712b82c2a5SDouglas Gregor return findModule(Name); 2722b82c2a5SDouglas Gregor 273eb90e830SDouglas Gregor return Context->findSubmodule(Name); 2742b82c2a5SDouglas Gregor } 2752b82c2a5SDouglas Gregor 276de3ef502SDouglas Gregor std::pair<Module *, bool> 27769021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 27869021974SDouglas Gregor bool IsExplicit) { 27969021974SDouglas Gregor // Try to find an existing module with this name. 280eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 281eb90e830SDouglas Gregor return std::make_pair(Sub, false); 28269021974SDouglas Gregor 28369021974SDouglas Gregor // Create a new module with this name. 28469021974SDouglas Gregor Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 28569021974SDouglas Gregor IsExplicit); 286eb90e830SDouglas Gregor if (!Parent) 28769021974SDouglas Gregor Modules[Name] = Result; 28869021974SDouglas Gregor return std::make_pair(Result, true); 28969021974SDouglas Gregor } 29069021974SDouglas Gregor 291de3ef502SDouglas Gregor Module * 29256c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 293e89dbc1dSDouglas Gregor const DirectoryEntry *FrameworkDir, 294a686e1b0SDouglas Gregor bool IsSystem, 295e89dbc1dSDouglas Gregor Module *Parent) { 29656c64013SDouglas Gregor // Check whether we've already found this module. 297e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 298e89dbc1dSDouglas Gregor return Mod; 299e89dbc1dSDouglas Gregor 300e89dbc1dSDouglas Gregor FileManager &FileMgr = SourceMgr->getFileManager(); 30156c64013SDouglas Gregor 30256c64013SDouglas Gregor // Look for an umbrella header. 3032c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 30456c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 30556c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 306e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 30756c64013SDouglas Gregor 30856c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 30956c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 31056c64013SDouglas Gregor // idea. 31156c64013SDouglas Gregor if (!UmbrellaHeader) 31256c64013SDouglas Gregor return 0; 31356c64013SDouglas Gregor 314e89dbc1dSDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), Parent, 315e89dbc1dSDouglas Gregor /*IsFramework=*/true, /*IsExplicit=*/false); 316a686e1b0SDouglas Gregor if (IsSystem) 317a686e1b0SDouglas Gregor Result->IsSystem = IsSystem; 318a686e1b0SDouglas Gregor 319eb90e830SDouglas Gregor if (!Parent) 320e89dbc1dSDouglas Gregor Modules[ModuleName] = Result; 321e89dbc1dSDouglas Gregor 322322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 32373141fa9SDouglas Gregor Result->Umbrella = UmbrellaHeader; 32456c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 3254dc71835SDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Result; 326d8bd7537SDouglas Gregor 327d8bd7537SDouglas Gregor // export * 328d8bd7537SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 329d8bd7537SDouglas Gregor 330a89c5ac4SDouglas Gregor // module * { export * } 331a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 332a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 333a89c5ac4SDouglas Gregor 334e89dbc1dSDouglas Gregor // Look for subframeworks. 335e89dbc1dSDouglas Gregor llvm::error_code EC; 3362c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 337ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 338e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 3392c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirNameNative; 340ddaa69cbSDouglas Gregor llvm::sys::path::native(SubframeworksDirName.str(), 341ddaa69cbSDouglas Gregor SubframeworksDirNameNative); 342ddaa69cbSDouglas Gregor for (llvm::sys::fs::directory_iterator 343ddaa69cbSDouglas Gregor Dir(SubframeworksDirNameNative.str(), EC), DirEnd; 344e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 345e89dbc1dSDouglas Gregor if (!StringRef(Dir->path()).endswith(".framework")) 346e89dbc1dSDouglas Gregor continue; 347f2161a70SDouglas Gregor 348e89dbc1dSDouglas Gregor if (const DirectoryEntry *SubframeworkDir 349e89dbc1dSDouglas Gregor = FileMgr.getDirectory(Dir->path())) { 350*07c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 351*07c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 352*07c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 353*07c22b78SDouglas Gregor // out to a top-level framework. 354*07c22b78SDouglas Gregor #ifdef LLVM_ON_UNIX 355*07c22b78SDouglas Gregor char RealSubframeworkDirName[PATH_MAX]; 356*07c22b78SDouglas Gregor if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) { 357*07c22b78SDouglas Gregor StringRef SubframeworkDirName = RealSubframeworkDirName; 358*07c22b78SDouglas Gregor 359*07c22b78SDouglas Gregor bool FoundParent = false; 360*07c22b78SDouglas Gregor do { 361*07c22b78SDouglas Gregor // Get the parent directory name. 362*07c22b78SDouglas Gregor SubframeworkDirName 363*07c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 364*07c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 365*07c22b78SDouglas Gregor break; 366*07c22b78SDouglas Gregor 367*07c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 368*07c22b78SDouglas Gregor FoundParent = true; 369*07c22b78SDouglas Gregor break; 370*07c22b78SDouglas Gregor } 371*07c22b78SDouglas Gregor } while (true); 372*07c22b78SDouglas Gregor 373*07c22b78SDouglas Gregor if (!FoundParent) 374*07c22b78SDouglas Gregor continue; 375*07c22b78SDouglas Gregor } 376*07c22b78SDouglas Gregor #endif 377*07c22b78SDouglas Gregor 378e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 379e89dbc1dSDouglas Gregor inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir, 380a686e1b0SDouglas Gregor IsSystem, Result); 381e89dbc1dSDouglas Gregor } 382e89dbc1dSDouglas Gregor } 383e89dbc1dSDouglas Gregor 38456c64013SDouglas Gregor return Result; 38556c64013SDouglas Gregor } 38656c64013SDouglas Gregor 387a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ 388a89c5ac4SDouglas Gregor Headers[UmbrellaHeader] = Mod; 38973141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 3907033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 391a89c5ac4SDouglas Gregor } 392a89c5ac4SDouglas Gregor 393524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) { 394524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 395524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 396524e33e1SDouglas Gregor } 397524e33e1SDouglas Gregor 398a89c5ac4SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) { 399a89c5ac4SDouglas Gregor Mod->Headers.push_back(Header); 400a89c5ac4SDouglas Gregor Headers[Header] = Mod; 401a89c5ac4SDouglas Gregor } 402a89c5ac4SDouglas Gregor 403514b636aSDouglas Gregor const FileEntry * 404de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 405514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 406514b636aSDouglas Gregor return 0; 407514b636aSDouglas Gregor 408514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 409514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 410514b636aSDouglas Gregor } 411514b636aSDouglas Gregor 412718292f2SDouglas Gregor void ModuleMap::dump() { 413718292f2SDouglas Gregor llvm::errs() << "Modules:"; 414718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 415718292f2SDouglas Gregor MEnd = Modules.end(); 416718292f2SDouglas Gregor M != MEnd; ++M) 417d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 418718292f2SDouglas Gregor 419718292f2SDouglas Gregor llvm::errs() << "Headers:"; 420718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 421718292f2SDouglas Gregor H = Headers.begin(), 422718292f2SDouglas Gregor HEnd = Headers.end(); 423718292f2SDouglas Gregor H != HEnd; ++H) { 424718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 425718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 426718292f2SDouglas Gregor } 427718292f2SDouglas Gregor } 428718292f2SDouglas Gregor 4292b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 4302b82c2a5SDouglas Gregor bool HadError = false; 4312b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 4322b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 4332b82c2a5SDouglas Gregor Complain); 434f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 4352b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 4362b82c2a5SDouglas Gregor else 4372b82c2a5SDouglas Gregor HadError = true; 4382b82c2a5SDouglas Gregor } 4392b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 4402b82c2a5SDouglas Gregor return HadError; 4412b82c2a5SDouglas Gregor } 4422b82c2a5SDouglas Gregor 4430093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { 4440093b3c7SDouglas Gregor if (Loc.isInvalid()) 4450093b3c7SDouglas Gregor return 0; 4460093b3c7SDouglas Gregor 4470093b3c7SDouglas Gregor // Use the expansion location to determine which module we're in. 4480093b3c7SDouglas Gregor FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); 4490093b3c7SDouglas Gregor if (!ExpansionLoc.isFileID()) 4500093b3c7SDouglas Gregor return 0; 4510093b3c7SDouglas Gregor 4520093b3c7SDouglas Gregor 4530093b3c7SDouglas Gregor const SourceManager &SrcMgr = Loc.getManager(); 4540093b3c7SDouglas Gregor FileID ExpansionFileID = ExpansionLoc.getFileID(); 455224d8a74SDouglas Gregor 456224d8a74SDouglas Gregor while (const FileEntry *ExpansionFile 457224d8a74SDouglas Gregor = SrcMgr.getFileEntryForID(ExpansionFileID)) { 458224d8a74SDouglas Gregor // Find the module that owns this header (if any). 459224d8a74SDouglas Gregor if (Module *Mod = findModuleForHeader(ExpansionFile)) 460224d8a74SDouglas Gregor return Mod; 461224d8a74SDouglas Gregor 462224d8a74SDouglas Gregor // No module owns this header, so look up the inclusion chain to see if 463224d8a74SDouglas Gregor // any included header has an associated module. 464224d8a74SDouglas Gregor SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID); 465224d8a74SDouglas Gregor if (IncludeLoc.isInvalid()) 4660093b3c7SDouglas Gregor return 0; 4670093b3c7SDouglas Gregor 468224d8a74SDouglas Gregor ExpansionFileID = SrcMgr.getFileID(IncludeLoc); 469224d8a74SDouglas Gregor } 470224d8a74SDouglas Gregor 471224d8a74SDouglas Gregor return 0; 4720093b3c7SDouglas Gregor } 4730093b3c7SDouglas Gregor 474718292f2SDouglas Gregor //----------------------------------------------------------------------------// 475718292f2SDouglas Gregor // Module map file parser 476718292f2SDouglas Gregor //----------------------------------------------------------------------------// 477718292f2SDouglas Gregor 478718292f2SDouglas Gregor namespace clang { 479718292f2SDouglas Gregor /// \brief A token in a module map file. 480718292f2SDouglas Gregor struct MMToken { 481718292f2SDouglas Gregor enum TokenKind { 4821fb5c3a6SDouglas Gregor Comma, 483718292f2SDouglas Gregor EndOfFile, 484718292f2SDouglas Gregor HeaderKeyword, 485718292f2SDouglas Gregor Identifier, 486718292f2SDouglas Gregor ExplicitKeyword, 4872b82c2a5SDouglas Gregor ExportKeyword, 488755b2055SDouglas Gregor FrameworkKeyword, 489718292f2SDouglas Gregor ModuleKeyword, 4902b82c2a5SDouglas Gregor Period, 491718292f2SDouglas Gregor UmbrellaKeyword, 4921fb5c3a6SDouglas Gregor RequiresKeyword, 4932b82c2a5SDouglas Gregor Star, 494718292f2SDouglas Gregor StringLiteral, 495718292f2SDouglas Gregor LBrace, 496a686e1b0SDouglas Gregor RBrace, 497a686e1b0SDouglas Gregor LSquare, 498a686e1b0SDouglas Gregor RSquare 499718292f2SDouglas Gregor } Kind; 500718292f2SDouglas Gregor 501718292f2SDouglas Gregor unsigned Location; 502718292f2SDouglas Gregor unsigned StringLength; 503718292f2SDouglas Gregor const char *StringData; 504718292f2SDouglas Gregor 505718292f2SDouglas Gregor void clear() { 506718292f2SDouglas Gregor Kind = EndOfFile; 507718292f2SDouglas Gregor Location = 0; 508718292f2SDouglas Gregor StringLength = 0; 509718292f2SDouglas Gregor StringData = 0; 510718292f2SDouglas Gregor } 511718292f2SDouglas Gregor 512718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 513718292f2SDouglas Gregor 514718292f2SDouglas Gregor SourceLocation getLocation() const { 515718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 516718292f2SDouglas Gregor } 517718292f2SDouglas Gregor 518718292f2SDouglas Gregor StringRef getString() const { 519718292f2SDouglas Gregor return StringRef(StringData, StringLength); 520718292f2SDouglas Gregor } 521718292f2SDouglas Gregor }; 522718292f2SDouglas Gregor 523718292f2SDouglas Gregor class ModuleMapParser { 524718292f2SDouglas Gregor Lexer &L; 525718292f2SDouglas Gregor SourceManager &SourceMgr; 526718292f2SDouglas Gregor DiagnosticsEngine &Diags; 527718292f2SDouglas Gregor ModuleMap ⤅ 528718292f2SDouglas Gregor 5295257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 5305257fc63SDouglas Gregor const DirectoryEntry *Directory; 5315257fc63SDouglas Gregor 5323ec6663bSDouglas Gregor /// \brief The directory containing Clang-supplied headers. 5333ec6663bSDouglas Gregor const DirectoryEntry *BuiltinIncludeDir; 5343ec6663bSDouglas Gregor 535718292f2SDouglas Gregor /// \brief Whether an error occurred. 536718292f2SDouglas Gregor bool HadError; 537718292f2SDouglas Gregor 538718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 539718292f2SDouglas Gregor /// parsing. 5403e2320c8SBenjamin Kramer OwningPtr<TargetInfo> Target; 541718292f2SDouglas Gregor 542718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 543718292f2SDouglas Gregor /// during parsing. 544718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 545718292f2SDouglas Gregor 546718292f2SDouglas Gregor /// \brief The current token. 547718292f2SDouglas Gregor MMToken Tok; 548718292f2SDouglas Gregor 549718292f2SDouglas Gregor /// \brief The active module. 550de3ef502SDouglas Gregor Module *ActiveModule; 551718292f2SDouglas Gregor 552718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 553718292f2SDouglas Gregor SourceLocation consumeToken(); 554718292f2SDouglas Gregor 555718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 556718292f2SDouglas Gregor /// (or the end of the file). 557718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 558718292f2SDouglas Gregor 559e7ab3669SDouglas Gregor typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2> 560e7ab3669SDouglas Gregor ModuleId; 561e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 562718292f2SDouglas Gregor void parseModuleDecl(); 5631fb5c3a6SDouglas Gregor void parseRequiresDecl(); 564322f633cSDouglas Gregor void parseHeaderDecl(SourceLocation UmbrellaLoc); 565524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 5662b82c2a5SDouglas Gregor void parseExportDecl(); 56773441091SDouglas Gregor void parseInferredSubmoduleDecl(bool Explicit); 568718292f2SDouglas Gregor 5697033127bSDouglas Gregor const DirectoryEntry *getOverriddenHeaderSearchDir(); 5707033127bSDouglas Gregor 571718292f2SDouglas Gregor public: 572718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 573718292f2SDouglas Gregor DiagnosticsEngine &Diags, 5745257fc63SDouglas Gregor ModuleMap &Map, 5753ec6663bSDouglas Gregor const DirectoryEntry *Directory, 5763ec6663bSDouglas Gregor const DirectoryEntry *BuiltinIncludeDir) 5775257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 5783ec6663bSDouglas Gregor Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir), 5793ec6663bSDouglas Gregor HadError(false), ActiveModule(0) 580718292f2SDouglas Gregor { 581718292f2SDouglas Gregor TargetOptions TargetOpts; 582718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 5833e2320c8SBenjamin Kramer Target.reset(TargetInfo::CreateTargetInfo(Diags, TargetOpts)); 584718292f2SDouglas Gregor 585718292f2SDouglas Gregor Tok.clear(); 586718292f2SDouglas Gregor consumeToken(); 587718292f2SDouglas Gregor } 588718292f2SDouglas Gregor 589718292f2SDouglas Gregor bool parseModuleMapFile(); 590718292f2SDouglas Gregor }; 591718292f2SDouglas Gregor } 592718292f2SDouglas Gregor 593718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 594718292f2SDouglas Gregor retry: 595718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 596718292f2SDouglas Gregor Tok.clear(); 597718292f2SDouglas Gregor 598718292f2SDouglas Gregor Token LToken; 599718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 600718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 601718292f2SDouglas Gregor switch (LToken.getKind()) { 602718292f2SDouglas Gregor case tok::raw_identifier: 603718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 604718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 605718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 606718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 607718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 6082b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 609755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 610718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 6111fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 612718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 613718292f2SDouglas Gregor .Default(MMToken::Identifier); 614718292f2SDouglas Gregor break; 615718292f2SDouglas Gregor 6161fb5c3a6SDouglas Gregor case tok::comma: 6171fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 6181fb5c3a6SDouglas Gregor break; 6191fb5c3a6SDouglas Gregor 620718292f2SDouglas Gregor case tok::eof: 621718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 622718292f2SDouglas Gregor break; 623718292f2SDouglas Gregor 624718292f2SDouglas Gregor case tok::l_brace: 625718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 626718292f2SDouglas Gregor break; 627718292f2SDouglas Gregor 628a686e1b0SDouglas Gregor case tok::l_square: 629a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 630a686e1b0SDouglas Gregor break; 631a686e1b0SDouglas Gregor 6322b82c2a5SDouglas Gregor case tok::period: 6332b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 6342b82c2a5SDouglas Gregor break; 6352b82c2a5SDouglas Gregor 636718292f2SDouglas Gregor case tok::r_brace: 637718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 638718292f2SDouglas Gregor break; 639718292f2SDouglas Gregor 640a686e1b0SDouglas Gregor case tok::r_square: 641a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 642a686e1b0SDouglas Gregor break; 643a686e1b0SDouglas Gregor 6442b82c2a5SDouglas Gregor case tok::star: 6452b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 6462b82c2a5SDouglas Gregor break; 6472b82c2a5SDouglas Gregor 648718292f2SDouglas Gregor case tok::string_literal: { 649d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 650d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 651d67aea28SRichard Smith HadError = true; 652d67aea28SRichard Smith goto retry; 653d67aea28SRichard Smith } 654d67aea28SRichard Smith 655718292f2SDouglas Gregor // Parse the string literal. 656718292f2SDouglas Gregor LangOptions LangOpts; 657718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 658718292f2SDouglas Gregor if (StringLiteral.hadError) 659718292f2SDouglas Gregor goto retry; 660718292f2SDouglas Gregor 661718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 662718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 663718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 664718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 665718292f2SDouglas Gregor Saved[Length] = 0; 666718292f2SDouglas Gregor 667718292f2SDouglas Gregor // Form the token. 668718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 669718292f2SDouglas Gregor Tok.StringData = Saved; 670718292f2SDouglas Gregor Tok.StringLength = Length; 671718292f2SDouglas Gregor break; 672718292f2SDouglas Gregor } 673718292f2SDouglas Gregor 674718292f2SDouglas Gregor case tok::comment: 675718292f2SDouglas Gregor goto retry; 676718292f2SDouglas Gregor 677718292f2SDouglas Gregor default: 678718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 679718292f2SDouglas Gregor HadError = true; 680718292f2SDouglas Gregor goto retry; 681718292f2SDouglas Gregor } 682718292f2SDouglas Gregor 683718292f2SDouglas Gregor return Result; 684718292f2SDouglas Gregor } 685718292f2SDouglas Gregor 686718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 687718292f2SDouglas Gregor unsigned braceDepth = 0; 688a686e1b0SDouglas Gregor unsigned squareDepth = 0; 689718292f2SDouglas Gregor do { 690718292f2SDouglas Gregor switch (Tok.Kind) { 691718292f2SDouglas Gregor case MMToken::EndOfFile: 692718292f2SDouglas Gregor return; 693718292f2SDouglas Gregor 694718292f2SDouglas Gregor case MMToken::LBrace: 695a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 696718292f2SDouglas Gregor return; 697718292f2SDouglas Gregor 698718292f2SDouglas Gregor ++braceDepth; 699718292f2SDouglas Gregor break; 700718292f2SDouglas Gregor 701a686e1b0SDouglas Gregor case MMToken::LSquare: 702a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 703a686e1b0SDouglas Gregor return; 704a686e1b0SDouglas Gregor 705a686e1b0SDouglas Gregor ++squareDepth; 706a686e1b0SDouglas Gregor break; 707a686e1b0SDouglas Gregor 708718292f2SDouglas Gregor case MMToken::RBrace: 709718292f2SDouglas Gregor if (braceDepth > 0) 710718292f2SDouglas Gregor --braceDepth; 711718292f2SDouglas Gregor else if (Tok.is(K)) 712718292f2SDouglas Gregor return; 713718292f2SDouglas Gregor break; 714718292f2SDouglas Gregor 715a686e1b0SDouglas Gregor case MMToken::RSquare: 716a686e1b0SDouglas Gregor if (squareDepth > 0) 717a686e1b0SDouglas Gregor --squareDepth; 718a686e1b0SDouglas Gregor else if (Tok.is(K)) 719a686e1b0SDouglas Gregor return; 720a686e1b0SDouglas Gregor break; 721a686e1b0SDouglas Gregor 722718292f2SDouglas Gregor default: 723a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 724718292f2SDouglas Gregor return; 725718292f2SDouglas Gregor break; 726718292f2SDouglas Gregor } 727718292f2SDouglas Gregor 728718292f2SDouglas Gregor consumeToken(); 729718292f2SDouglas Gregor } while (true); 730718292f2SDouglas Gregor } 731718292f2SDouglas Gregor 732e7ab3669SDouglas Gregor /// \brief Parse a module-id. 733e7ab3669SDouglas Gregor /// 734e7ab3669SDouglas Gregor /// module-id: 735e7ab3669SDouglas Gregor /// identifier 736e7ab3669SDouglas Gregor /// identifier '.' module-id 737e7ab3669SDouglas Gregor /// 738e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 739e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 740e7ab3669SDouglas Gregor Id.clear(); 741e7ab3669SDouglas Gregor do { 742e7ab3669SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 743e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 744e7ab3669SDouglas Gregor consumeToken(); 745e7ab3669SDouglas Gregor } else { 746e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 747e7ab3669SDouglas Gregor return true; 748e7ab3669SDouglas Gregor } 749e7ab3669SDouglas Gregor 750e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 751e7ab3669SDouglas Gregor break; 752e7ab3669SDouglas Gregor 753e7ab3669SDouglas Gregor consumeToken(); 754e7ab3669SDouglas Gregor } while (true); 755e7ab3669SDouglas Gregor 756e7ab3669SDouglas Gregor return false; 757e7ab3669SDouglas Gregor } 758e7ab3669SDouglas Gregor 759a686e1b0SDouglas Gregor namespace { 760a686e1b0SDouglas Gregor /// \brief Enumerates the known attributes. 761a686e1b0SDouglas Gregor enum AttributeKind { 762a686e1b0SDouglas Gregor /// \brief An unknown attribute. 763a686e1b0SDouglas Gregor AT_unknown, 764a686e1b0SDouglas Gregor /// \brief The 'system' attribute. 765a686e1b0SDouglas Gregor AT_system 766a686e1b0SDouglas Gregor }; 767a686e1b0SDouglas Gregor } 768a686e1b0SDouglas Gregor 769718292f2SDouglas Gregor /// \brief Parse a module declaration. 770718292f2SDouglas Gregor /// 771718292f2SDouglas Gregor /// module-declaration: 772a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 773a686e1b0SDouglas Gregor /// { module-member* } 774a686e1b0SDouglas Gregor /// 775a686e1b0SDouglas Gregor /// attributes: 776a686e1b0SDouglas Gregor /// attribute attributes 777a686e1b0SDouglas Gregor /// attribute 778a686e1b0SDouglas Gregor /// 779a686e1b0SDouglas Gregor /// attribute: 780a686e1b0SDouglas Gregor /// [ identifier ] 781718292f2SDouglas Gregor /// 782718292f2SDouglas Gregor /// module-member: 7831fb5c3a6SDouglas Gregor /// requires-declaration 784718292f2SDouglas Gregor /// header-declaration 785e7ab3669SDouglas Gregor /// submodule-declaration 7862b82c2a5SDouglas Gregor /// export-declaration 78773441091SDouglas Gregor /// 78873441091SDouglas Gregor /// submodule-declaration: 78973441091SDouglas Gregor /// module-declaration 79073441091SDouglas Gregor /// inferred-submodule-declaration 791718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 792755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 793755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 794f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 795e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 796718292f2SDouglas Gregor bool Explicit = false; 797f2161a70SDouglas Gregor bool Framework = false; 798755b2055SDouglas Gregor 799f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 800f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 801e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 802f2161a70SDouglas Gregor Explicit = true; 803f2161a70SDouglas Gregor } 804f2161a70SDouglas Gregor 805f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 806755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 807755b2055SDouglas Gregor consumeToken(); 808755b2055SDouglas Gregor Framework = true; 809755b2055SDouglas Gregor } 810718292f2SDouglas Gregor 811718292f2SDouglas Gregor // Parse 'module' keyword. 812718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 813d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 814718292f2SDouglas Gregor consumeToken(); 815718292f2SDouglas Gregor HadError = true; 816718292f2SDouglas Gregor return; 817718292f2SDouglas Gregor } 818718292f2SDouglas Gregor consumeToken(); // 'module' keyword 819718292f2SDouglas Gregor 82073441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 82173441091SDouglas Gregor // Parse it. 82273441091SDouglas Gregor if (Tok.is(MMToken::Star)) 82373441091SDouglas Gregor return parseInferredSubmoduleDecl(Explicit); 82473441091SDouglas Gregor 825718292f2SDouglas Gregor // Parse the module name. 826e7ab3669SDouglas Gregor ModuleId Id; 827e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 828718292f2SDouglas Gregor HadError = true; 829718292f2SDouglas Gregor return; 830718292f2SDouglas Gregor } 831e7ab3669SDouglas Gregor 832e7ab3669SDouglas Gregor if (ActiveModule) { 833e7ab3669SDouglas Gregor if (Id.size() > 1) { 834e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 835e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 836e7ab3669SDouglas Gregor 837e7ab3669SDouglas Gregor HadError = true; 838e7ab3669SDouglas Gregor return; 839e7ab3669SDouglas Gregor } 840e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 841e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 842e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 843e7ab3669SDouglas Gregor Explicit = false; 844e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 845e7ab3669SDouglas Gregor HadError = true; 846e7ab3669SDouglas Gregor } 847e7ab3669SDouglas Gregor 848e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 849e7ab3669SDouglas Gregor if (Id.size() > 1) { 850e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 851e7ab3669SDouglas Gregor // is a submodule. 852e7ab3669SDouglas Gregor ActiveModule = 0; 853e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 854e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 855e7ab3669SDouglas Gregor ActiveModule = Next; 856e7ab3669SDouglas Gregor continue; 857e7ab3669SDouglas Gregor } 858e7ab3669SDouglas Gregor 859e7ab3669SDouglas Gregor if (ActiveModule) { 860e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 861e7ab3669SDouglas Gregor << Id[I].first << ActiveModule->getTopLevelModule(); 862e7ab3669SDouglas Gregor } else { 863e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 864e7ab3669SDouglas Gregor } 865e7ab3669SDouglas Gregor HadError = true; 866e7ab3669SDouglas Gregor return; 867e7ab3669SDouglas Gregor } 868e7ab3669SDouglas Gregor } 869e7ab3669SDouglas Gregor 870e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 871e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 872718292f2SDouglas Gregor 873a686e1b0SDouglas Gregor // Parse the optional attribute list. 874a686e1b0SDouglas Gregor bool IsSystem = false; 875a686e1b0SDouglas Gregor while (Tok.is(MMToken::LSquare)) { 876a686e1b0SDouglas Gregor // Consume the '['. 877a686e1b0SDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 878a686e1b0SDouglas Gregor 879a686e1b0SDouglas Gregor // Check whether we have an attribute name here. 880a686e1b0SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 881a686e1b0SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 882a686e1b0SDouglas Gregor skipUntil(MMToken::RSquare); 883a686e1b0SDouglas Gregor if (Tok.is(MMToken::RSquare)) 884a686e1b0SDouglas Gregor consumeToken(); 885a686e1b0SDouglas Gregor continue; 886a686e1b0SDouglas Gregor } 887a686e1b0SDouglas Gregor 888a686e1b0SDouglas Gregor // Decode the attribute name. 889a686e1b0SDouglas Gregor AttributeKind Attribute 890a686e1b0SDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 891a686e1b0SDouglas Gregor .Case("system", AT_system) 892a686e1b0SDouglas Gregor .Default(AT_unknown); 893a686e1b0SDouglas Gregor switch (Attribute) { 894a686e1b0SDouglas Gregor case AT_unknown: 895a686e1b0SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 896a686e1b0SDouglas Gregor << Tok.getString(); 897a686e1b0SDouglas Gregor break; 898a686e1b0SDouglas Gregor 899a686e1b0SDouglas Gregor case AT_system: 900a686e1b0SDouglas Gregor IsSystem = true; 901a686e1b0SDouglas Gregor break; 902a686e1b0SDouglas Gregor } 903a686e1b0SDouglas Gregor consumeToken(); 904a686e1b0SDouglas Gregor 905a686e1b0SDouglas Gregor // Consume the ']'. 906a686e1b0SDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 907a686e1b0SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 908a686e1b0SDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 909a686e1b0SDouglas Gregor skipUntil(MMToken::RSquare); 910a686e1b0SDouglas Gregor } 911a686e1b0SDouglas Gregor 912a686e1b0SDouglas Gregor if (Tok.is(MMToken::RSquare)) 913a686e1b0SDouglas Gregor consumeToken(); 914a686e1b0SDouglas Gregor } 915a686e1b0SDouglas Gregor 916718292f2SDouglas Gregor // Parse the opening brace. 917718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 918718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 919718292f2SDouglas Gregor << ModuleName; 920718292f2SDouglas Gregor HadError = true; 921718292f2SDouglas Gregor return; 922718292f2SDouglas Gregor } 923718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 924718292f2SDouglas Gregor 925718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 926eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 927fcc54a3bSDouglas Gregor if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) { 928fcc54a3bSDouglas Gregor // Skip the module definition. 929fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 930fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 931fcc54a3bSDouglas Gregor consumeToken(); 932fcc54a3bSDouglas Gregor else { 933fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 934fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 935fcc54a3bSDouglas Gregor HadError = true; 936fcc54a3bSDouglas Gregor } 937fcc54a3bSDouglas Gregor return; 938fcc54a3bSDouglas Gregor } 939fcc54a3bSDouglas Gregor 940718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 941718292f2SDouglas Gregor << ModuleName; 942eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 943718292f2SDouglas Gregor 944718292f2SDouglas Gregor // Skip the module definition. 945718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 946718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 947718292f2SDouglas Gregor consumeToken(); 948718292f2SDouglas Gregor 949718292f2SDouglas Gregor HadError = true; 950718292f2SDouglas Gregor return; 951718292f2SDouglas Gregor } 952718292f2SDouglas Gregor 953718292f2SDouglas Gregor // Start defining this module. 954eb90e830SDouglas Gregor ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, 955eb90e830SDouglas Gregor Explicit).first; 956eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 957a686e1b0SDouglas Gregor if (IsSystem) 958a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 959718292f2SDouglas Gregor 960718292f2SDouglas Gregor bool Done = false; 961718292f2SDouglas Gregor do { 962718292f2SDouglas Gregor switch (Tok.Kind) { 963718292f2SDouglas Gregor case MMToken::EndOfFile: 964718292f2SDouglas Gregor case MMToken::RBrace: 965718292f2SDouglas Gregor Done = true; 966718292f2SDouglas Gregor break; 967718292f2SDouglas Gregor 968718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 969f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 970718292f2SDouglas Gregor case MMToken::ModuleKeyword: 971718292f2SDouglas Gregor parseModuleDecl(); 972718292f2SDouglas Gregor break; 973718292f2SDouglas Gregor 9742b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 9752b82c2a5SDouglas Gregor parseExportDecl(); 9762b82c2a5SDouglas Gregor break; 9772b82c2a5SDouglas Gregor 9781fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 9791fb5c3a6SDouglas Gregor parseRequiresDecl(); 9801fb5c3a6SDouglas Gregor break; 9811fb5c3a6SDouglas Gregor 982524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 983524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 984524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 985524e33e1SDouglas Gregor parseHeaderDecl(UmbrellaLoc); 986524e33e1SDouglas Gregor else 987524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 988718292f2SDouglas Gregor break; 989524e33e1SDouglas Gregor } 990718292f2SDouglas Gregor 991322f633cSDouglas Gregor case MMToken::HeaderKeyword: 992322f633cSDouglas Gregor parseHeaderDecl(SourceLocation()); 993718292f2SDouglas Gregor break; 994718292f2SDouglas Gregor 995718292f2SDouglas Gregor default: 996718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 997718292f2SDouglas Gregor consumeToken(); 998718292f2SDouglas Gregor break; 999718292f2SDouglas Gregor } 1000718292f2SDouglas Gregor } while (!Done); 1001718292f2SDouglas Gregor 1002718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1003718292f2SDouglas Gregor consumeToken(); 1004718292f2SDouglas Gregor else { 1005718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1006718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1007718292f2SDouglas Gregor HadError = true; 1008718292f2SDouglas Gregor } 1009718292f2SDouglas Gregor 1010e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 1011e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 1012718292f2SDouglas Gregor } 1013718292f2SDouglas Gregor 10141fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration. 10151fb5c3a6SDouglas Gregor /// 10161fb5c3a6SDouglas Gregor /// requires-declaration: 10171fb5c3a6SDouglas Gregor /// 'requires' feature-list 10181fb5c3a6SDouglas Gregor /// 10191fb5c3a6SDouglas Gregor /// feature-list: 10201fb5c3a6SDouglas Gregor /// identifier ',' feature-list 10211fb5c3a6SDouglas Gregor /// identifier 10221fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 10231fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 10241fb5c3a6SDouglas Gregor 10251fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 10261fb5c3a6SDouglas Gregor consumeToken(); 10271fb5c3a6SDouglas Gregor 10281fb5c3a6SDouglas Gregor // Parse the feature-list. 10291fb5c3a6SDouglas Gregor do { 10301fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 10311fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 10321fb5c3a6SDouglas Gregor HadError = true; 10331fb5c3a6SDouglas Gregor return; 10341fb5c3a6SDouglas Gregor } 10351fb5c3a6SDouglas Gregor 10361fb5c3a6SDouglas Gregor // Consume the feature name. 10371fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 10381fb5c3a6SDouglas Gregor consumeToken(); 10391fb5c3a6SDouglas Gregor 10401fb5c3a6SDouglas Gregor // Add this feature. 104189929282SDouglas Gregor ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target); 10421fb5c3a6SDouglas Gregor 10431fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 10441fb5c3a6SDouglas Gregor break; 10451fb5c3a6SDouglas Gregor 10461fb5c3a6SDouglas Gregor // Consume the comma. 10471fb5c3a6SDouglas Gregor consumeToken(); 10481fb5c3a6SDouglas Gregor } while (true); 10491fb5c3a6SDouglas Gregor } 10501fb5c3a6SDouglas Gregor 1051f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the 1052f2161a70SDouglas Gregor /// subframework in which the given module lives. 1053bf8da9d7SBenjamin Kramer static void appendSubframeworkPaths(Module *Mod, 1054bf8da9d7SBenjamin Kramer llvm::SmallVectorImpl<char> &Path) { 1055f2161a70SDouglas Gregor // Collect the framework names from the given module to the top-level module. 1056f2161a70SDouglas Gregor llvm::SmallVector<StringRef, 2> Paths; 1057f2161a70SDouglas Gregor for (; Mod; Mod = Mod->Parent) { 1058f2161a70SDouglas Gregor if (Mod->IsFramework) 1059f2161a70SDouglas Gregor Paths.push_back(Mod->Name); 1060f2161a70SDouglas Gregor } 1061f2161a70SDouglas Gregor 1062f2161a70SDouglas Gregor if (Paths.empty()) 1063f2161a70SDouglas Gregor return; 1064f2161a70SDouglas Gregor 1065f2161a70SDouglas Gregor // Add Frameworks/Name.framework for each subframework. 1066f2161a70SDouglas Gregor for (unsigned I = Paths.size() - 1; I != 0; --I) { 1067f2161a70SDouglas Gregor llvm::sys::path::append(Path, "Frameworks"); 1068f2161a70SDouglas Gregor llvm::sys::path::append(Path, Paths[I-1] + ".framework"); 1069f2161a70SDouglas Gregor } 1070f2161a70SDouglas Gregor } 1071f2161a70SDouglas Gregor 10723ec6663bSDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin 10733ec6663bSDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 10743ec6663bSDouglas Gregor /// headers. 10753ec6663bSDouglas Gregor static bool isBuiltinHeader(StringRef FileName) { 10763ec6663bSDouglas Gregor return llvm::StringSwitch<bool>(FileName) 10773ec6663bSDouglas Gregor .Case("float.h", true) 10783ec6663bSDouglas Gregor .Case("iso646.h", true) 10793ec6663bSDouglas Gregor .Case("limits.h", true) 10803ec6663bSDouglas Gregor .Case("stdalign.h", true) 10813ec6663bSDouglas Gregor .Case("stdarg.h", true) 10823ec6663bSDouglas Gregor .Case("stdbool.h", true) 10833ec6663bSDouglas Gregor .Case("stddef.h", true) 10843ec6663bSDouglas Gregor .Case("stdint.h", true) 10853ec6663bSDouglas Gregor .Case("tgmath.h", true) 10863ec6663bSDouglas Gregor .Case("unwind.h", true) 10873ec6663bSDouglas Gregor .Default(false); 10883ec6663bSDouglas Gregor } 10893ec6663bSDouglas Gregor 1090718292f2SDouglas Gregor /// \brief Parse a header declaration. 1091718292f2SDouglas Gregor /// 1092718292f2SDouglas Gregor /// header-declaration: 1093322f633cSDouglas Gregor /// 'umbrella'[opt] 'header' string-literal 1094322f633cSDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { 1095718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 10961871ed3dSBenjamin Kramer consumeToken(); 1097718292f2SDouglas Gregor 1098322f633cSDouglas Gregor bool Umbrella = UmbrellaLoc.isValid(); 1099322f633cSDouglas Gregor 1100718292f2SDouglas Gregor // Parse the header name. 1101718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1102718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 1103718292f2SDouglas Gregor << "header"; 1104718292f2SDouglas Gregor HadError = true; 1105718292f2SDouglas Gregor return; 1106718292f2SDouglas Gregor } 1107e7ab3669SDouglas Gregor std::string FileName = Tok.getString(); 1108718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 1109718292f2SDouglas Gregor 1110524e33e1SDouglas Gregor // Check whether we already have an umbrella. 1111524e33e1SDouglas Gregor if (Umbrella && ActiveModule->Umbrella) { 1112524e33e1SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash) 1113524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 1114322f633cSDouglas Gregor HadError = true; 1115322f633cSDouglas Gregor return; 1116322f633cSDouglas Gregor } 1117322f633cSDouglas Gregor 11185257fc63SDouglas Gregor // Look for this file. 1119e7ab3669SDouglas Gregor const FileEntry *File = 0; 11203ec6663bSDouglas Gregor const FileEntry *BuiltinFile = 0; 11212c1dd271SDylan Noblesmith SmallString<128> PathName; 1122e7ab3669SDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 1123e7ab3669SDouglas Gregor PathName = FileName; 1124e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 11257033127bSDouglas Gregor } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) { 11267033127bSDouglas Gregor PathName = Dir->getName(); 11277033127bSDouglas Gregor llvm::sys::path::append(PathName, FileName); 11287033127bSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1129e7ab3669SDouglas Gregor } else { 1130e7ab3669SDouglas Gregor // Search for the header file within the search directory. 11317033127bSDouglas Gregor PathName = Directory->getName(); 1132e7ab3669SDouglas Gregor unsigned PathLength = PathName.size(); 1133755b2055SDouglas Gregor 1134f2161a70SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 1135f2161a70SDouglas Gregor appendSubframeworkPaths(ActiveModule, PathName); 1136755b2055SDouglas Gregor 1137e7ab3669SDouglas Gregor // Check whether this file is in the public headers. 1138e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 11395257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1140e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1141e7ab3669SDouglas Gregor 1142e7ab3669SDouglas Gregor if (!File) { 1143e7ab3669SDouglas Gregor // Check whether this file is in the private headers. 1144e7ab3669SDouglas Gregor PathName.resize(PathLength); 1145e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 1146e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1147e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1148e7ab3669SDouglas Gregor } 1149e7ab3669SDouglas Gregor } else { 1150e7ab3669SDouglas Gregor // Lookup for normal headers. 1151e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1152e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 11533ec6663bSDouglas Gregor 11543ec6663bSDouglas Gregor // If this is a system module with a top-level header, this header 11553ec6663bSDouglas Gregor // may have a counterpart (or replacement) in the set of headers 11563ec6663bSDouglas Gregor // supplied by Clang. Find that builtin header. 11573ec6663bSDouglas Gregor if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir && 11583ec6663bSDouglas Gregor BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) { 11592c1dd271SDylan Noblesmith SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); 11603ec6663bSDouglas Gregor llvm::sys::path::append(BuiltinPathName, FileName); 11613ec6663bSDouglas Gregor BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); 11623ec6663bSDouglas Gregor 11633ec6663bSDouglas Gregor // If Clang supplies this header but the underlying system does not, 11643ec6663bSDouglas Gregor // just silently swap in our builtin version. Otherwise, we'll end 11653ec6663bSDouglas Gregor // up adding both (later). 11663ec6663bSDouglas Gregor if (!File && BuiltinFile) { 11673ec6663bSDouglas Gregor File = BuiltinFile; 11683ec6663bSDouglas Gregor BuiltinFile = 0; 11693ec6663bSDouglas Gregor } 11703ec6663bSDouglas Gregor } 1171e7ab3669SDouglas Gregor } 1172e7ab3669SDouglas Gregor } 11735257fc63SDouglas Gregor 11745257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 11755257fc63SDouglas Gregor // Come up with a lazy way to do this. 1176e7ab3669SDouglas Gregor if (File) { 11775257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 11785257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 11795257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 11805257fc63SDouglas Gregor HadError = true; 1181322f633cSDouglas Gregor } else if (Umbrella) { 1182322f633cSDouglas Gregor const DirectoryEntry *UmbrellaDir = File->getDir(); 1183322f633cSDouglas Gregor if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) { 1184322f633cSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 1185322f633cSDouglas Gregor << OwningModule->getFullModuleName(); 1186322f633cSDouglas Gregor HadError = true; 11875257fc63SDouglas Gregor } else { 1188322f633cSDouglas Gregor // Record this umbrella header. 1189322f633cSDouglas Gregor Map.setUmbrellaHeader(ActiveModule, File); 1190322f633cSDouglas Gregor } 1191322f633cSDouglas Gregor } else { 1192322f633cSDouglas Gregor // Record this header. 1193a89c5ac4SDouglas Gregor Map.addHeader(ActiveModule, File); 11943ec6663bSDouglas Gregor 11953ec6663bSDouglas Gregor // If there is a builtin counterpart to this file, add it now. 11963ec6663bSDouglas Gregor if (BuiltinFile) 11973ec6663bSDouglas Gregor Map.addHeader(ActiveModule, BuiltinFile); 11985257fc63SDouglas Gregor } 11995257fc63SDouglas Gregor } else { 12005257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 1201524e33e1SDouglas Gregor << Umbrella << FileName; 12025257fc63SDouglas Gregor HadError = true; 12035257fc63SDouglas Gregor } 1204718292f2SDouglas Gregor } 1205718292f2SDouglas Gregor 1206524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration. 1207524e33e1SDouglas Gregor /// 1208524e33e1SDouglas Gregor /// umbrella-dir-declaration: 1209524e33e1SDouglas Gregor /// umbrella string-literal 1210524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 1211524e33e1SDouglas Gregor // Parse the directory name. 1212524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1213524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 1214524e33e1SDouglas Gregor << "umbrella"; 1215524e33e1SDouglas Gregor HadError = true; 1216524e33e1SDouglas Gregor return; 1217524e33e1SDouglas Gregor } 1218524e33e1SDouglas Gregor 1219524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 1220524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 1221524e33e1SDouglas Gregor 1222524e33e1SDouglas Gregor // Check whether we already have an umbrella. 1223524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 1224524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 1225524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 1226524e33e1SDouglas Gregor HadError = true; 1227524e33e1SDouglas Gregor return; 1228524e33e1SDouglas Gregor } 1229524e33e1SDouglas Gregor 1230524e33e1SDouglas Gregor // Look for this file. 1231524e33e1SDouglas Gregor const DirectoryEntry *Dir = 0; 1232524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 1233524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 1234524e33e1SDouglas Gregor else { 12352c1dd271SDylan Noblesmith SmallString<128> PathName; 1236524e33e1SDouglas Gregor PathName = Directory->getName(); 1237524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 1238524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 1239524e33e1SDouglas Gregor } 1240524e33e1SDouglas Gregor 1241524e33e1SDouglas Gregor if (!Dir) { 1242524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found) 1243524e33e1SDouglas Gregor << DirName; 1244524e33e1SDouglas Gregor HadError = true; 1245524e33e1SDouglas Gregor return; 1246524e33e1SDouglas Gregor } 1247524e33e1SDouglas Gregor 1248524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 1249524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 1250524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 1251524e33e1SDouglas Gregor HadError = true; 1252524e33e1SDouglas Gregor return; 1253524e33e1SDouglas Gregor } 1254524e33e1SDouglas Gregor 1255524e33e1SDouglas Gregor // Record this umbrella directory. 1256524e33e1SDouglas Gregor Map.setUmbrellaDir(ActiveModule, Dir); 1257524e33e1SDouglas Gregor } 1258524e33e1SDouglas Gregor 12592b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 12602b82c2a5SDouglas Gregor /// 12612b82c2a5SDouglas Gregor /// export-declaration: 12622b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 12632b82c2a5SDouglas Gregor /// 12642b82c2a5SDouglas Gregor /// wildcard-module-id: 12652b82c2a5SDouglas Gregor /// identifier 12662b82c2a5SDouglas Gregor /// '*' 12672b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 12682b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 12692b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 12702b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 12712b82c2a5SDouglas Gregor 12722b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 12732b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 12742b82c2a5SDouglas Gregor bool Wildcard = false; 12752b82c2a5SDouglas Gregor do { 12762b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 12772b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 12782b82c2a5SDouglas Gregor Tok.getLocation())); 12792b82c2a5SDouglas Gregor consumeToken(); 12802b82c2a5SDouglas Gregor 12812b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 12822b82c2a5SDouglas Gregor consumeToken(); 12832b82c2a5SDouglas Gregor continue; 12842b82c2a5SDouglas Gregor } 12852b82c2a5SDouglas Gregor 12862b82c2a5SDouglas Gregor break; 12872b82c2a5SDouglas Gregor } 12882b82c2a5SDouglas Gregor 12892b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 12902b82c2a5SDouglas Gregor Wildcard = true; 1291f5eedd05SDouglas Gregor consumeToken(); 12922b82c2a5SDouglas Gregor break; 12932b82c2a5SDouglas Gregor } 12942b82c2a5SDouglas Gregor 12952b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 12962b82c2a5SDouglas Gregor HadError = true; 12972b82c2a5SDouglas Gregor return; 12982b82c2a5SDouglas Gregor } while (true); 12992b82c2a5SDouglas Gregor 13002b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 13012b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 13022b82c2a5SDouglas Gregor }; 13032b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 13042b82c2a5SDouglas Gregor } 13052b82c2a5SDouglas Gregor 130673441091SDouglas Gregor void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { 130773441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 130873441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 130973441091SDouglas Gregor bool Failed = false; 131073441091SDouglas Gregor 131173441091SDouglas Gregor // Inferred modules must be submodules. 131273441091SDouglas Gregor if (!ActiveModule) { 131373441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 131473441091SDouglas Gregor Failed = true; 131573441091SDouglas Gregor } 131673441091SDouglas Gregor 1317524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 1318524e33e1SDouglas Gregor if (!Failed && !ActiveModule->getUmbrellaDir()) { 131973441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 132073441091SDouglas Gregor Failed = true; 132173441091SDouglas Gregor } 132273441091SDouglas Gregor 132373441091SDouglas Gregor // Check for redefinition of an inferred module. 1324dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 132573441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 1326dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 1327dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 132873441091SDouglas Gregor diag::note_mmap_prev_definition); 132973441091SDouglas Gregor Failed = true; 133073441091SDouglas Gregor } 133173441091SDouglas Gregor 133273441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 133373441091SDouglas Gregor if (Failed) { 133473441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 133573441091SDouglas Gregor consumeToken(); 133673441091SDouglas Gregor skipUntil(MMToken::RBrace); 133773441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 133873441091SDouglas Gregor consumeToken(); 133973441091SDouglas Gregor } 134073441091SDouglas Gregor HadError = true; 134173441091SDouglas Gregor return; 134273441091SDouglas Gregor } 134373441091SDouglas Gregor 134473441091SDouglas Gregor // Note that we have an inferred submodule. 1345dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 1346dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 1347dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 134873441091SDouglas Gregor 134973441091SDouglas Gregor // Parse the opening brace. 135073441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 135173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 135273441091SDouglas Gregor HadError = true; 135373441091SDouglas Gregor return; 135473441091SDouglas Gregor } 135573441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 135673441091SDouglas Gregor 135773441091SDouglas Gregor // Parse the body of the inferred submodule. 135873441091SDouglas Gregor bool Done = false; 135973441091SDouglas Gregor do { 136073441091SDouglas Gregor switch (Tok.Kind) { 136173441091SDouglas Gregor case MMToken::EndOfFile: 136273441091SDouglas Gregor case MMToken::RBrace: 136373441091SDouglas Gregor Done = true; 136473441091SDouglas Gregor break; 136573441091SDouglas Gregor 136673441091SDouglas Gregor case MMToken::ExportKeyword: { 136773441091SDouglas Gregor consumeToken(); 136873441091SDouglas Gregor if (Tok.is(MMToken::Star)) 1369dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 137073441091SDouglas Gregor else 137173441091SDouglas Gregor Diags.Report(Tok.getLocation(), 137273441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 137373441091SDouglas Gregor consumeToken(); 137473441091SDouglas Gregor break; 137573441091SDouglas Gregor } 137673441091SDouglas Gregor 137773441091SDouglas Gregor case MMToken::ExplicitKeyword: 137873441091SDouglas Gregor case MMToken::ModuleKeyword: 137973441091SDouglas Gregor case MMToken::HeaderKeyword: 138073441091SDouglas Gregor case MMToken::UmbrellaKeyword: 138173441091SDouglas Gregor default: 138273441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member); 138373441091SDouglas Gregor consumeToken(); 138473441091SDouglas Gregor break; 138573441091SDouglas Gregor } 138673441091SDouglas Gregor } while (!Done); 138773441091SDouglas Gregor 138873441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 138973441091SDouglas Gregor consumeToken(); 139073441091SDouglas Gregor else { 139173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 139273441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 139373441091SDouglas Gregor HadError = true; 139473441091SDouglas Gregor } 139573441091SDouglas Gregor } 139673441091SDouglas Gregor 13977033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence 13987033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null. 13997033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() { 14007033127bSDouglas Gregor for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) { 14017033127bSDouglas Gregor // If we have an umbrella directory, use that. 14027033127bSDouglas Gregor if (Mod->hasUmbrellaDir()) 14037033127bSDouglas Gregor return Mod->getUmbrellaDir(); 14047033127bSDouglas Gregor 14057033127bSDouglas Gregor // If we have a framework directory, stop looking. 14067033127bSDouglas Gregor if (Mod->IsFramework) 14077033127bSDouglas Gregor return 0; 14087033127bSDouglas Gregor } 14097033127bSDouglas Gregor 14107033127bSDouglas Gregor return 0; 14117033127bSDouglas Gregor } 14127033127bSDouglas Gregor 1413718292f2SDouglas Gregor /// \brief Parse a module map file. 1414718292f2SDouglas Gregor /// 1415718292f2SDouglas Gregor /// module-map-file: 1416718292f2SDouglas Gregor /// module-declaration* 1417718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 1418718292f2SDouglas Gregor do { 1419718292f2SDouglas Gregor switch (Tok.Kind) { 1420718292f2SDouglas Gregor case MMToken::EndOfFile: 1421718292f2SDouglas Gregor return HadError; 1422718292f2SDouglas Gregor 1423e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 1424718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1425755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 1426718292f2SDouglas Gregor parseModuleDecl(); 1427718292f2SDouglas Gregor break; 1428718292f2SDouglas Gregor 14291fb5c3a6SDouglas Gregor case MMToken::Comma: 14302b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 1431718292f2SDouglas Gregor case MMToken::HeaderKeyword: 1432718292f2SDouglas Gregor case MMToken::Identifier: 1433718292f2SDouglas Gregor case MMToken::LBrace: 1434a686e1b0SDouglas Gregor case MMToken::LSquare: 14352b82c2a5SDouglas Gregor case MMToken::Period: 1436718292f2SDouglas Gregor case MMToken::RBrace: 1437a686e1b0SDouglas Gregor case MMToken::RSquare: 14381fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 14392b82c2a5SDouglas Gregor case MMToken::Star: 1440718292f2SDouglas Gregor case MMToken::StringLiteral: 1441718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 1442718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1443718292f2SDouglas Gregor HadError = true; 1444718292f2SDouglas Gregor consumeToken(); 1445718292f2SDouglas Gregor break; 1446718292f2SDouglas Gregor } 1447718292f2SDouglas Gregor } while (true); 1448718292f2SDouglas Gregor } 1449718292f2SDouglas Gregor 1450718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 145189929282SDouglas Gregor assert(Target != 0 && "Missing target information"); 1452718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 1453718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 1454718292f2SDouglas Gregor if (!Buffer) 1455718292f2SDouglas Gregor return true; 1456718292f2SDouglas Gregor 1457718292f2SDouglas Gregor // Parse this module map file. 14581fb5c3a6SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts); 14591fb5c3a6SDouglas Gregor Diags->getClient()->BeginSourceFile(MMapLangOpts); 14603ec6663bSDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir(), 14613ec6663bSDouglas Gregor BuiltinIncludeDir); 1462718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 1463718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 1464718292f2SDouglas Gregor 1465718292f2SDouglas Gregor return Result; 1466718292f2SDouglas Gregor } 1467