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/Basic/Diagnostic.h" 16811db4eaSDouglas Gregor #include "clang/Basic/DiagnosticOptions.h" 17718292f2SDouglas Gregor #include "clang/Basic/FileManager.h" 18718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h" 19718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h" 203a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h" 213a02247dSChandler Carruth #include "clang/Lex/Lexer.h" 223a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h" 233a02247dSChandler Carruth #include "llvm/ADT/StringRef.h" 243a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h" 25718292f2SDouglas Gregor #include "llvm/Support/Allocator.h" 26e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h" 27718292f2SDouglas Gregor #include "llvm/Support/Host.h" 285257fc63SDouglas Gregor #include "llvm/Support/PathV2.h" 29718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 3007c22b78SDouglas Gregor #include <stdlib.h> 31718292f2SDouglas Gregor using namespace clang; 32718292f2SDouglas Gregor 332b82c2a5SDouglas Gregor Module::ExportDecl 342b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 352b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 362b82c2a5SDouglas Gregor bool Complain) { 37f5eedd05SDouglas Gregor // We may have just a wildcard. 38f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 39f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 40f5eedd05SDouglas Gregor return Module::ExportDecl(0, true); 41f5eedd05SDouglas Gregor } 42f5eedd05SDouglas Gregor 432b82c2a5SDouglas Gregor // Find the starting module. 442b82c2a5SDouglas Gregor Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod); 452b82c2a5SDouglas Gregor if (!Context) { 462b82c2a5SDouglas Gregor if (Complain) 472b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[0].second, 482b82c2a5SDouglas Gregor diag::err_mmap_missing_module_unqualified) 492b82c2a5SDouglas Gregor << Unresolved.Id[0].first << Mod->getFullModuleName(); 502b82c2a5SDouglas Gregor 512b82c2a5SDouglas Gregor return Module::ExportDecl(); 522b82c2a5SDouglas Gregor } 532b82c2a5SDouglas Gregor 542b82c2a5SDouglas Gregor // Dig into the module path. 552b82c2a5SDouglas Gregor for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) { 562b82c2a5SDouglas Gregor Module *Sub = lookupModuleQualified(Unresolved.Id[I].first, 572b82c2a5SDouglas Gregor Context); 582b82c2a5SDouglas Gregor if (!Sub) { 592b82c2a5SDouglas Gregor if (Complain) 602b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[I].second, 612b82c2a5SDouglas Gregor diag::err_mmap_missing_module_qualified) 622b82c2a5SDouglas Gregor << Unresolved.Id[I].first << Context->getFullModuleName() 632b82c2a5SDouglas Gregor << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second); 642b82c2a5SDouglas Gregor 652b82c2a5SDouglas Gregor return Module::ExportDecl(); 662b82c2a5SDouglas Gregor } 672b82c2a5SDouglas Gregor 682b82c2a5SDouglas Gregor Context = Sub; 692b82c2a5SDouglas Gregor } 702b82c2a5SDouglas Gregor 712b82c2a5SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 722b82c2a5SDouglas Gregor } 732b82c2a5SDouglas Gregor 741fb5c3a6SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, 7589929282SDouglas Gregor const LangOptions &LangOpts, const TargetInfo *Target) 763ec6663bSDouglas Gregor : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0) 771fb5c3a6SDouglas Gregor { 78c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 79c95d8192SDylan Noblesmith Diags = IntrusiveRefCntPtr<DiagnosticsEngine>( 80811db4eaSDouglas Gregor new DiagnosticsEngine(DiagIDs, new DiagnosticOptions)); 81718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 82718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 83718292f2SDouglas Gregor } 84718292f2SDouglas Gregor 85718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 865acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 875acdf59eSDouglas Gregor IEnd = Modules.end(); 885acdf59eSDouglas Gregor I != IEnd; ++I) { 895acdf59eSDouglas Gregor delete I->getValue(); 905acdf59eSDouglas Gregor } 915acdf59eSDouglas Gregor 92718292f2SDouglas Gregor delete SourceMgr; 93718292f2SDouglas Gregor } 94718292f2SDouglas Gregor 9589929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 9689929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 9789929282SDouglas Gregor "Improper target override"); 9889929282SDouglas Gregor this->Target = &Target; 9989929282SDouglas Gregor } 10089929282SDouglas Gregor 101056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier. 102056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name, 103056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) { 104056396aeSDouglas Gregor if (Name.empty()) 105056396aeSDouglas Gregor return Name; 106056396aeSDouglas Gregor 107056396aeSDouglas Gregor // Check whether the filename is already an identifier; this is the common 108056396aeSDouglas Gregor // case. 109056396aeSDouglas Gregor bool isIdentifier = true; 110056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 111056396aeSDouglas Gregor if (isalpha(Name[I]) || Name[I] == '_' || (isdigit(Name[I]) && I > 0)) 112056396aeSDouglas Gregor continue; 113056396aeSDouglas Gregor 114056396aeSDouglas Gregor isIdentifier = false; 115056396aeSDouglas Gregor break; 116056396aeSDouglas Gregor } 117056396aeSDouglas Gregor 118056396aeSDouglas Gregor if (!isIdentifier) { 119056396aeSDouglas Gregor // If we don't already have something with the form of an identifier, 120056396aeSDouglas Gregor // create a buffer with the sanitized name. 121056396aeSDouglas Gregor Buffer.clear(); 122056396aeSDouglas Gregor if (isdigit(Name[0])) 123056396aeSDouglas Gregor Buffer.push_back('_'); 124056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size()); 125056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 126056396aeSDouglas Gregor if (isalnum(Name[I]) || isspace(Name[I])) 127056396aeSDouglas Gregor Buffer.push_back(Name[I]); 128056396aeSDouglas Gregor else 129056396aeSDouglas Gregor Buffer.push_back('_'); 130056396aeSDouglas Gregor } 131056396aeSDouglas Gregor 132056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 133056396aeSDouglas Gregor } 134056396aeSDouglas Gregor 135056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name) 136056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) 137056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) 138056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def" 139056396aeSDouglas Gregor .Default(false)) { 140056396aeSDouglas Gregor if (Name.data() != Buffer.data()) 141056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end()); 142056396aeSDouglas Gregor Buffer.push_back('_'); 143056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 144056396aeSDouglas Gregor } 145056396aeSDouglas Gregor 146056396aeSDouglas Gregor return Name; 147056396aeSDouglas Gregor } 148056396aeSDouglas Gregor 149de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 15059527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 1511fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 15259527666SDouglas Gregor // If a header is not available, don't report that it maps to anything. 15359527666SDouglas Gregor if (!Known->second.isAvailable()) 1541fb5c3a6SDouglas Gregor return 0; 1551fb5c3a6SDouglas Gregor 15659527666SDouglas Gregor return Known->second.getModule(); 1571fb5c3a6SDouglas Gregor } 158ab0c8a84SDouglas Gregor 159b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 160f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 16174260502SDouglas Gregor #ifdef LLVM_ON_UNIX 16274260502SDouglas Gregor // Note: as an egregious but useful hack we use the real path here, because 16374260502SDouglas Gregor // frameworks moving from top-level frameworks to embedded frameworks tend 16474260502SDouglas Gregor // to be symlinked from the top-level location to the embedded location, 16574260502SDouglas Gregor // and we need to resolve lookups as if we had found the embedded location. 16674260502SDouglas Gregor char RealDirName[PATH_MAX]; 16774260502SDouglas Gregor StringRef DirName; 16874260502SDouglas Gregor if (realpath(Dir->getName(), RealDirName)) 16974260502SDouglas Gregor DirName = RealDirName; 17074260502SDouglas Gregor else 17174260502SDouglas Gregor DirName = Dir->getName(); 17274260502SDouglas Gregor #else 173b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 17474260502SDouglas Gregor #endif 175a89c5ac4SDouglas Gregor 176a89c5ac4SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 177a89c5ac4SDouglas Gregor // an umbrella header. 178b65dbfffSDouglas Gregor do { 179a89c5ac4SDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 180a89c5ac4SDouglas Gregor = UmbrellaDirs.find(Dir); 181a89c5ac4SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 182a89c5ac4SDouglas Gregor Module *Result = KnownDir->second; 183930a85ccSDouglas Gregor 184930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 18573141fa9SDouglas Gregor // directory. 186930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 18773141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 188930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 189930a85ccSDouglas Gregor 190930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 191a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 192a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 193a89c5ac4SDouglas Gregor // the actual header is located. 1949458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 1959458f82dSDouglas Gregor 1967033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 197a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 198056396aeSDouglas Gregor SmallString<32> NameBuf; 199056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 200056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 201056396aeSDouglas Gregor NameBuf); 202a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 2039458f82dSDouglas Gregor Explicit).first; 204a89c5ac4SDouglas Gregor 205a89c5ac4SDouglas Gregor // Associate the module and the directory. 206a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 207a89c5ac4SDouglas Gregor 208a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 209a89c5ac4SDouglas Gregor // wildcard to the set of exports. 210930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 211a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 212a89c5ac4SDouglas Gregor } 213a89c5ac4SDouglas Gregor 214a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 215056396aeSDouglas Gregor SmallString<32> NameBuf; 216056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 217056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 218a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 2199458f82dSDouglas Gregor Explicit).first; 220c597c8c4SArgyrios Kyrtzidis Result->TopHeaders.insert(File); 221a89c5ac4SDouglas Gregor 222a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 223a89c5ac4SDouglas Gregor // wildcard to the set of exports. 224930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 225a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 226a89c5ac4SDouglas Gregor } else { 227a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 228a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 229a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 230a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 231a89c5ac4SDouglas Gregor } 232a89c5ac4SDouglas Gregor 23359527666SDouglas Gregor Headers[File] = KnownHeader(Result, /*Excluded=*/false); 2341fb5c3a6SDouglas Gregor 2351fb5c3a6SDouglas Gregor // If a header corresponds to an unavailable module, don't report 2361fb5c3a6SDouglas Gregor // that it maps to anything. 2371fb5c3a6SDouglas Gregor if (!Result->isAvailable()) 2381fb5c3a6SDouglas Gregor return 0; 2391fb5c3a6SDouglas Gregor 240a89c5ac4SDouglas Gregor return Result; 241a89c5ac4SDouglas Gregor } 242a89c5ac4SDouglas Gregor 243a89c5ac4SDouglas Gregor SkippedDirs.push_back(Dir); 244a89c5ac4SDouglas Gregor 245b65dbfffSDouglas Gregor // Retrieve our parent path. 246b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 247b65dbfffSDouglas Gregor if (DirName.empty()) 248b65dbfffSDouglas Gregor break; 249b65dbfffSDouglas Gregor 250b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 251b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 252a89c5ac4SDouglas Gregor } while (Dir); 253b65dbfffSDouglas Gregor 254ab0c8a84SDouglas Gregor return 0; 255ab0c8a84SDouglas Gregor } 256ab0c8a84SDouglas Gregor 2571fb5c3a6SDouglas Gregor bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) { 25859527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(Header); 2591fb5c3a6SDouglas Gregor if (Known != Headers.end()) 26059527666SDouglas Gregor return !Known->second.isAvailable(); 2611fb5c3a6SDouglas Gregor 2621fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 263f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 2641fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 2651fb5c3a6SDouglas Gregor 2661fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 2671fb5c3a6SDouglas Gregor // an umbrella header. 2681fb5c3a6SDouglas Gregor do { 2691fb5c3a6SDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 2701fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 2711fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 2721fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 2731fb5c3a6SDouglas Gregor if (!Found->isAvailable()) 2741fb5c3a6SDouglas Gregor return true; 2751fb5c3a6SDouglas Gregor 2761fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 2771fb5c3a6SDouglas Gregor // directory. 2781fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 2791fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 2801fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 2811fb5c3a6SDouglas Gregor 2821fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 2831fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 2841fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 285056396aeSDouglas Gregor SmallString<32> NameBuf; 286056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 287056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 288056396aeSDouglas Gregor NameBuf); 2891fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 2901fb5c3a6SDouglas Gregor if (!Found) 2911fb5c3a6SDouglas Gregor return false; 2921fb5c3a6SDouglas Gregor if (!Found->isAvailable()) 2931fb5c3a6SDouglas Gregor return true; 2941fb5c3a6SDouglas Gregor } 2951fb5c3a6SDouglas Gregor 2961fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 297056396aeSDouglas Gregor SmallString<32> NameBuf; 298056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 299056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 300056396aeSDouglas Gregor NameBuf); 3011fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 3021fb5c3a6SDouglas Gregor if (!Found) 3031fb5c3a6SDouglas Gregor return false; 3041fb5c3a6SDouglas Gregor } 3051fb5c3a6SDouglas Gregor 3061fb5c3a6SDouglas Gregor return !Found->isAvailable(); 3071fb5c3a6SDouglas Gregor } 3081fb5c3a6SDouglas Gregor 3091fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 3101fb5c3a6SDouglas Gregor 3111fb5c3a6SDouglas Gregor // Retrieve our parent path. 3121fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 3131fb5c3a6SDouglas Gregor if (DirName.empty()) 3141fb5c3a6SDouglas Gregor break; 3151fb5c3a6SDouglas Gregor 3161fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 3171fb5c3a6SDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 3181fb5c3a6SDouglas Gregor } while (Dir); 3191fb5c3a6SDouglas Gregor 3201fb5c3a6SDouglas Gregor return false; 3211fb5c3a6SDouglas Gregor } 3221fb5c3a6SDouglas Gregor 323de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) { 32488bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 32588bdfb0eSDouglas Gregor if (Known != Modules.end()) 32688bdfb0eSDouglas Gregor return Known->getValue(); 32788bdfb0eSDouglas Gregor 32888bdfb0eSDouglas Gregor return 0; 32988bdfb0eSDouglas Gregor } 33088bdfb0eSDouglas Gregor 3312b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) { 3322b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 3332b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 3342b82c2a5SDouglas Gregor return Sub; 3352b82c2a5SDouglas Gregor } 3362b82c2a5SDouglas Gregor 3372b82c2a5SDouglas Gregor return findModule(Name); 3382b82c2a5SDouglas Gregor } 3392b82c2a5SDouglas Gregor 3402b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) { 3412b82c2a5SDouglas Gregor if (!Context) 3422b82c2a5SDouglas Gregor return findModule(Name); 3432b82c2a5SDouglas Gregor 344eb90e830SDouglas Gregor return Context->findSubmodule(Name); 3452b82c2a5SDouglas Gregor } 3462b82c2a5SDouglas Gregor 347de3ef502SDouglas Gregor std::pair<Module *, bool> 34869021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 34969021974SDouglas Gregor bool IsExplicit) { 35069021974SDouglas Gregor // Try to find an existing module with this name. 351eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 352eb90e830SDouglas Gregor return std::make_pair(Sub, false); 35369021974SDouglas Gregor 35469021974SDouglas Gregor // Create a new module with this name. 35569021974SDouglas Gregor Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 35669021974SDouglas Gregor IsExplicit); 357eb90e830SDouglas Gregor if (!Parent) 35869021974SDouglas Gregor Modules[Name] = Result; 35969021974SDouglas Gregor return std::make_pair(Result, true); 36069021974SDouglas Gregor } 36169021974SDouglas Gregor 3629194a91dSDouglas Gregor bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir, 3639194a91dSDouglas Gregor StringRef Name, bool &IsSystem) { 3649194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 3659194a91dSDouglas Gregor // for a module map. 3669194a91dSDouglas Gregor llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator 3679194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 3689194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 3699194a91dSDouglas Gregor return false; 3709194a91dSDouglas Gregor 3719194a91dSDouglas Gregor if (!inferred->second.InferModules) 3729194a91dSDouglas Gregor return false; 3739194a91dSDouglas Gregor 3749194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 3759194a91dSDouglas Gregor // to infer this particular module. 3769194a91dSDouglas Gregor bool canInfer = std::find(inferred->second.ExcludedModules.begin(), 3779194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 3789194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 3799194a91dSDouglas Gregor 3809194a91dSDouglas Gregor if (canInfer && inferred->second.InferSystemModules) 3819194a91dSDouglas Gregor IsSystem = true; 3829194a91dSDouglas Gregor 3839194a91dSDouglas Gregor return canInfer; 3849194a91dSDouglas Gregor } 3859194a91dSDouglas Gregor 386de3ef502SDouglas Gregor Module * 38756c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 388e89dbc1dSDouglas Gregor const DirectoryEntry *FrameworkDir, 389a686e1b0SDouglas Gregor bool IsSystem, 390e89dbc1dSDouglas Gregor Module *Parent) { 39156c64013SDouglas Gregor // Check whether we've already found this module. 392e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 393e89dbc1dSDouglas Gregor return Mod; 394e89dbc1dSDouglas Gregor 395e89dbc1dSDouglas Gregor FileManager &FileMgr = SourceMgr->getFileManager(); 39656c64013SDouglas Gregor 3979194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 3989194a91dSDouglas Gregor // a framework module, do so. 3999194a91dSDouglas Gregor if (!Parent) { 4004ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 4014ddf2221SDouglas Gregor StringRef FrameworkDirName = FrameworkDir->getName(); 4024ddf2221SDouglas Gregor #ifdef LLVM_ON_UNIX 4034ddf2221SDouglas Gregor // Note: as an egregious but useful hack we use the real path here, because 4044ddf2221SDouglas Gregor // we might be looking at an embedded framework that symlinks out to a 4054ddf2221SDouglas Gregor // top-level framework, and we need to infer as if we were naming the 4064ddf2221SDouglas Gregor // top-level framework. 4074ddf2221SDouglas Gregor char RealFrameworkDirName[PATH_MAX]; 4084ddf2221SDouglas Gregor if (realpath(FrameworkDir->getName(), RealFrameworkDirName)) 4094ddf2221SDouglas Gregor FrameworkDirName = RealFrameworkDirName; 4104ddf2221SDouglas Gregor #endif 4114ddf2221SDouglas Gregor 4129194a91dSDouglas Gregor bool canInfer = false; 4134ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 4149194a91dSDouglas Gregor // Figure out the parent path. 4154ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 4169194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 4179194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 4189194a91dSDouglas Gregor // for a module map. 4199194a91dSDouglas Gregor llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::iterator 4209194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 4219194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 4229194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 4239194a91dSDouglas Gregor // one. 4249194a91dSDouglas Gregor SmallString<128> ModMapPath = Parent; 4259194a91dSDouglas Gregor llvm::sys::path::append(ModMapPath, "module.map"); 4269194a91dSDouglas Gregor if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) { 4279194a91dSDouglas Gregor parseModuleMapFile(ModMapFile); 4289194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 4299194a91dSDouglas Gregor } 4309194a91dSDouglas Gregor 4319194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 4329194a91dSDouglas Gregor inferred = InferredDirectories.insert( 4339194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 4349194a91dSDouglas Gregor } 4359194a91dSDouglas Gregor 4369194a91dSDouglas Gregor if (inferred->second.InferModules) { 4379194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 4389194a91dSDouglas Gregor // to infer this particular module. 4394ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 4409194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 4419194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 4429194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 4439194a91dSDouglas Gregor 4449194a91dSDouglas Gregor if (inferred->second.InferSystemModules) 4459194a91dSDouglas Gregor IsSystem = true; 4469194a91dSDouglas Gregor } 4479194a91dSDouglas Gregor } 4489194a91dSDouglas Gregor } 4499194a91dSDouglas Gregor 4509194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 4519194a91dSDouglas Gregor if (!canInfer) 4529194a91dSDouglas Gregor return 0; 4539194a91dSDouglas Gregor } 4549194a91dSDouglas Gregor 4559194a91dSDouglas Gregor 45656c64013SDouglas Gregor // Look for an umbrella header. 4572c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 45856c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 45956c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 460e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 46156c64013SDouglas Gregor 46256c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 46356c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 46456c64013SDouglas Gregor // idea. 46556c64013SDouglas Gregor if (!UmbrellaHeader) 46656c64013SDouglas Gregor return 0; 46756c64013SDouglas Gregor 468e89dbc1dSDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), Parent, 469e89dbc1dSDouglas Gregor /*IsFramework=*/true, /*IsExplicit=*/false); 470a686e1b0SDouglas Gregor if (IsSystem) 471a686e1b0SDouglas Gregor Result->IsSystem = IsSystem; 472a686e1b0SDouglas Gregor 473eb90e830SDouglas Gregor if (!Parent) 474e89dbc1dSDouglas Gregor Modules[ModuleName] = Result; 475e89dbc1dSDouglas Gregor 476322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 47773141fa9SDouglas Gregor Result->Umbrella = UmbrellaHeader; 47859527666SDouglas Gregor Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false); 4794dc71835SDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Result; 480d8bd7537SDouglas Gregor 481d8bd7537SDouglas Gregor // export * 482d8bd7537SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 483d8bd7537SDouglas Gregor 484a89c5ac4SDouglas Gregor // module * { export * } 485a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 486a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 487a89c5ac4SDouglas Gregor 488e89dbc1dSDouglas Gregor // Look for subframeworks. 489e89dbc1dSDouglas Gregor llvm::error_code EC; 4902c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 491ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 492e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 4932c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirNameNative; 494ddaa69cbSDouglas Gregor llvm::sys::path::native(SubframeworksDirName.str(), 495ddaa69cbSDouglas Gregor SubframeworksDirNameNative); 496ddaa69cbSDouglas Gregor for (llvm::sys::fs::directory_iterator 497ddaa69cbSDouglas Gregor Dir(SubframeworksDirNameNative.str(), EC), DirEnd; 498e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 499e89dbc1dSDouglas Gregor if (!StringRef(Dir->path()).endswith(".framework")) 500e89dbc1dSDouglas Gregor continue; 501f2161a70SDouglas Gregor 502e89dbc1dSDouglas Gregor if (const DirectoryEntry *SubframeworkDir 503e89dbc1dSDouglas Gregor = FileMgr.getDirectory(Dir->path())) { 50407c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 50507c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 50607c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 50707c22b78SDouglas Gregor // out to a top-level framework. 50807c22b78SDouglas Gregor #ifdef LLVM_ON_UNIX 50907c22b78SDouglas Gregor char RealSubframeworkDirName[PATH_MAX]; 51007c22b78SDouglas Gregor if (realpath(Dir->path().c_str(), RealSubframeworkDirName)) { 51107c22b78SDouglas Gregor StringRef SubframeworkDirName = RealSubframeworkDirName; 51207c22b78SDouglas Gregor 51307c22b78SDouglas Gregor bool FoundParent = false; 51407c22b78SDouglas Gregor do { 51507c22b78SDouglas Gregor // Get the parent directory name. 51607c22b78SDouglas Gregor SubframeworkDirName 51707c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 51807c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 51907c22b78SDouglas Gregor break; 52007c22b78SDouglas Gregor 52107c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 52207c22b78SDouglas Gregor FoundParent = true; 52307c22b78SDouglas Gregor break; 52407c22b78SDouglas Gregor } 52507c22b78SDouglas Gregor } while (true); 52607c22b78SDouglas Gregor 52707c22b78SDouglas Gregor if (!FoundParent) 52807c22b78SDouglas Gregor continue; 52907c22b78SDouglas Gregor } 53007c22b78SDouglas Gregor #endif 53107c22b78SDouglas Gregor 532e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 533056396aeSDouglas Gregor SmallString<32> NameBuf; 534056396aeSDouglas Gregor inferFrameworkModule(sanitizeFilenameAsIdentifier( 535056396aeSDouglas Gregor llvm::sys::path::stem(Dir->path()), NameBuf), 536056396aeSDouglas Gregor SubframeworkDir, IsSystem, Result); 537e89dbc1dSDouglas Gregor } 538e89dbc1dSDouglas Gregor } 539e89dbc1dSDouglas Gregor 54056c64013SDouglas Gregor return Result; 54156c64013SDouglas Gregor } 54256c64013SDouglas Gregor 543a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ 54459527666SDouglas Gregor Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false); 54573141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 5467033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 547a89c5ac4SDouglas Gregor } 548a89c5ac4SDouglas Gregor 549524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) { 550524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 551524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 552524e33e1SDouglas Gregor } 553524e33e1SDouglas Gregor 55459527666SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header, 55559527666SDouglas Gregor bool Excluded) { 55659527666SDouglas Gregor if (Excluded) 55759527666SDouglas Gregor Mod->ExcludedHeaders.push_back(Header); 55859527666SDouglas Gregor else 559a89c5ac4SDouglas Gregor Mod->Headers.push_back(Header); 56059527666SDouglas Gregor Headers[Header] = KnownHeader(Mod, Excluded); 561a89c5ac4SDouglas Gregor } 562a89c5ac4SDouglas Gregor 563514b636aSDouglas Gregor const FileEntry * 564de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 565514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 566514b636aSDouglas Gregor return 0; 567514b636aSDouglas Gregor 568514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 569514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 570514b636aSDouglas Gregor } 571514b636aSDouglas Gregor 572718292f2SDouglas Gregor void ModuleMap::dump() { 573718292f2SDouglas Gregor llvm::errs() << "Modules:"; 574718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 575718292f2SDouglas Gregor MEnd = Modules.end(); 576718292f2SDouglas Gregor M != MEnd; ++M) 577d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 578718292f2SDouglas Gregor 579718292f2SDouglas Gregor llvm::errs() << "Headers:"; 58059527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 581718292f2SDouglas Gregor H != HEnd; ++H) { 582718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 58359527666SDouglas Gregor << H->second.getModule()->getFullModuleName() << "\n"; 584718292f2SDouglas Gregor } 585718292f2SDouglas Gregor } 586718292f2SDouglas Gregor 5872b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 5882b82c2a5SDouglas Gregor bool HadError = false; 5892b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 5902b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 5912b82c2a5SDouglas Gregor Complain); 592f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 5932b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 5942b82c2a5SDouglas Gregor else 5952b82c2a5SDouglas Gregor HadError = true; 5962b82c2a5SDouglas Gregor } 5972b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 5982b82c2a5SDouglas Gregor return HadError; 5992b82c2a5SDouglas Gregor } 6002b82c2a5SDouglas Gregor 6010093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { 6020093b3c7SDouglas Gregor if (Loc.isInvalid()) 6030093b3c7SDouglas Gregor return 0; 6040093b3c7SDouglas Gregor 6050093b3c7SDouglas Gregor // Use the expansion location to determine which module we're in. 6060093b3c7SDouglas Gregor FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); 6070093b3c7SDouglas Gregor if (!ExpansionLoc.isFileID()) 6080093b3c7SDouglas Gregor return 0; 6090093b3c7SDouglas Gregor 6100093b3c7SDouglas Gregor 6110093b3c7SDouglas Gregor const SourceManager &SrcMgr = Loc.getManager(); 6120093b3c7SDouglas Gregor FileID ExpansionFileID = ExpansionLoc.getFileID(); 613224d8a74SDouglas Gregor 614224d8a74SDouglas Gregor while (const FileEntry *ExpansionFile 615224d8a74SDouglas Gregor = SrcMgr.getFileEntryForID(ExpansionFileID)) { 616224d8a74SDouglas Gregor // Find the module that owns this header (if any). 617224d8a74SDouglas Gregor if (Module *Mod = findModuleForHeader(ExpansionFile)) 618224d8a74SDouglas Gregor return Mod; 619224d8a74SDouglas Gregor 620224d8a74SDouglas Gregor // No module owns this header, so look up the inclusion chain to see if 621224d8a74SDouglas Gregor // any included header has an associated module. 622224d8a74SDouglas Gregor SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID); 623224d8a74SDouglas Gregor if (IncludeLoc.isInvalid()) 6240093b3c7SDouglas Gregor return 0; 6250093b3c7SDouglas Gregor 626224d8a74SDouglas Gregor ExpansionFileID = SrcMgr.getFileID(IncludeLoc); 627224d8a74SDouglas Gregor } 628224d8a74SDouglas Gregor 629224d8a74SDouglas Gregor return 0; 6300093b3c7SDouglas Gregor } 6310093b3c7SDouglas Gregor 632718292f2SDouglas Gregor //----------------------------------------------------------------------------// 633718292f2SDouglas Gregor // Module map file parser 634718292f2SDouglas Gregor //----------------------------------------------------------------------------// 635718292f2SDouglas Gregor 636718292f2SDouglas Gregor namespace clang { 637718292f2SDouglas Gregor /// \brief A token in a module map file. 638718292f2SDouglas Gregor struct MMToken { 639718292f2SDouglas Gregor enum TokenKind { 6401fb5c3a6SDouglas Gregor Comma, 641718292f2SDouglas Gregor EndOfFile, 642718292f2SDouglas Gregor HeaderKeyword, 643718292f2SDouglas Gregor Identifier, 64459527666SDouglas Gregor ExcludeKeyword, 645718292f2SDouglas Gregor ExplicitKeyword, 6462b82c2a5SDouglas Gregor ExportKeyword, 647755b2055SDouglas Gregor FrameworkKeyword, 648*6ddfca91SDouglas Gregor LinkKeyword, 649718292f2SDouglas Gregor ModuleKeyword, 6502b82c2a5SDouglas Gregor Period, 651718292f2SDouglas Gregor UmbrellaKeyword, 6521fb5c3a6SDouglas Gregor RequiresKeyword, 6532b82c2a5SDouglas Gregor Star, 654718292f2SDouglas Gregor StringLiteral, 655718292f2SDouglas Gregor LBrace, 656a686e1b0SDouglas Gregor RBrace, 657a686e1b0SDouglas Gregor LSquare, 658a686e1b0SDouglas Gregor RSquare 659718292f2SDouglas Gregor } Kind; 660718292f2SDouglas Gregor 661718292f2SDouglas Gregor unsigned Location; 662718292f2SDouglas Gregor unsigned StringLength; 663718292f2SDouglas Gregor const char *StringData; 664718292f2SDouglas Gregor 665718292f2SDouglas Gregor void clear() { 666718292f2SDouglas Gregor Kind = EndOfFile; 667718292f2SDouglas Gregor Location = 0; 668718292f2SDouglas Gregor StringLength = 0; 669718292f2SDouglas Gregor StringData = 0; 670718292f2SDouglas Gregor } 671718292f2SDouglas Gregor 672718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 673718292f2SDouglas Gregor 674718292f2SDouglas Gregor SourceLocation getLocation() const { 675718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 676718292f2SDouglas Gregor } 677718292f2SDouglas Gregor 678718292f2SDouglas Gregor StringRef getString() const { 679718292f2SDouglas Gregor return StringRef(StringData, StringLength); 680718292f2SDouglas Gregor } 681718292f2SDouglas Gregor }; 682718292f2SDouglas Gregor 6839194a91dSDouglas Gregor /// \brief The set of attributes that can be attached to a module. 6844442605fSBill Wendling struct Attributes { 6854442605fSBill Wendling Attributes() : IsSystem() { } 6869194a91dSDouglas Gregor 6879194a91dSDouglas Gregor /// \brief Whether this is a system module. 6889194a91dSDouglas Gregor unsigned IsSystem : 1; 6899194a91dSDouglas Gregor }; 6909194a91dSDouglas Gregor 6919194a91dSDouglas Gregor 692718292f2SDouglas Gregor class ModuleMapParser { 693718292f2SDouglas Gregor Lexer &L; 694718292f2SDouglas Gregor SourceManager &SourceMgr; 695bc10b9fbSDouglas Gregor 696bc10b9fbSDouglas Gregor /// \brief Default target information, used only for string literal 697bc10b9fbSDouglas Gregor /// parsing. 698bc10b9fbSDouglas Gregor const TargetInfo *Target; 699bc10b9fbSDouglas Gregor 700718292f2SDouglas Gregor DiagnosticsEngine &Diags; 701718292f2SDouglas Gregor ModuleMap ⤅ 702718292f2SDouglas Gregor 7035257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 7045257fc63SDouglas Gregor const DirectoryEntry *Directory; 7055257fc63SDouglas Gregor 7063ec6663bSDouglas Gregor /// \brief The directory containing Clang-supplied headers. 7073ec6663bSDouglas Gregor const DirectoryEntry *BuiltinIncludeDir; 7083ec6663bSDouglas Gregor 709718292f2SDouglas Gregor /// \brief Whether an error occurred. 710718292f2SDouglas Gregor bool HadError; 711718292f2SDouglas Gregor 712718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 713718292f2SDouglas Gregor /// during parsing. 714718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 715718292f2SDouglas Gregor 716718292f2SDouglas Gregor /// \brief The current token. 717718292f2SDouglas Gregor MMToken Tok; 718718292f2SDouglas Gregor 719718292f2SDouglas Gregor /// \brief The active module. 720de3ef502SDouglas Gregor Module *ActiveModule; 721718292f2SDouglas Gregor 722718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 723718292f2SDouglas Gregor SourceLocation consumeToken(); 724718292f2SDouglas Gregor 725718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 726718292f2SDouglas Gregor /// (or the end of the file). 727718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 728718292f2SDouglas Gregor 729f857950dSDmitri Gribenko typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId; 730e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 731718292f2SDouglas Gregor void parseModuleDecl(); 7321fb5c3a6SDouglas Gregor void parseRequiresDecl(); 73359527666SDouglas Gregor void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc); 734524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 7352b82c2a5SDouglas Gregor void parseExportDecl(); 736*6ddfca91SDouglas Gregor void parseLinkDecl(); 7379194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 7384442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 739718292f2SDouglas Gregor 7407033127bSDouglas Gregor const DirectoryEntry *getOverriddenHeaderSearchDir(); 7417033127bSDouglas Gregor 742718292f2SDouglas Gregor public: 743718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 744bc10b9fbSDouglas Gregor const TargetInfo *Target, 745718292f2SDouglas Gregor DiagnosticsEngine &Diags, 7465257fc63SDouglas Gregor ModuleMap &Map, 7473ec6663bSDouglas Gregor const DirectoryEntry *Directory, 7483ec6663bSDouglas Gregor const DirectoryEntry *BuiltinIncludeDir) 749bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 7503ec6663bSDouglas Gregor Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir), 7513ec6663bSDouglas Gregor HadError(false), ActiveModule(0) 752718292f2SDouglas Gregor { 753718292f2SDouglas Gregor Tok.clear(); 754718292f2SDouglas Gregor consumeToken(); 755718292f2SDouglas Gregor } 756718292f2SDouglas Gregor 757718292f2SDouglas Gregor bool parseModuleMapFile(); 758718292f2SDouglas Gregor }; 759718292f2SDouglas Gregor } 760718292f2SDouglas Gregor 761718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 762718292f2SDouglas Gregor retry: 763718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 764718292f2SDouglas Gregor Tok.clear(); 765718292f2SDouglas Gregor 766718292f2SDouglas Gregor Token LToken; 767718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 768718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 769718292f2SDouglas Gregor switch (LToken.getKind()) { 770718292f2SDouglas Gregor case tok::raw_identifier: 771718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 772718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 773718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 774718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 77559527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 776718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 7772b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 778755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 779*6ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 780718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 7811fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 782718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 783718292f2SDouglas Gregor .Default(MMToken::Identifier); 784718292f2SDouglas Gregor break; 785718292f2SDouglas Gregor 7861fb5c3a6SDouglas Gregor case tok::comma: 7871fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 7881fb5c3a6SDouglas Gregor break; 7891fb5c3a6SDouglas Gregor 790718292f2SDouglas Gregor case tok::eof: 791718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 792718292f2SDouglas Gregor break; 793718292f2SDouglas Gregor 794718292f2SDouglas Gregor case tok::l_brace: 795718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 796718292f2SDouglas Gregor break; 797718292f2SDouglas Gregor 798a686e1b0SDouglas Gregor case tok::l_square: 799a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 800a686e1b0SDouglas Gregor break; 801a686e1b0SDouglas Gregor 8022b82c2a5SDouglas Gregor case tok::period: 8032b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 8042b82c2a5SDouglas Gregor break; 8052b82c2a5SDouglas Gregor 806718292f2SDouglas Gregor case tok::r_brace: 807718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 808718292f2SDouglas Gregor break; 809718292f2SDouglas Gregor 810a686e1b0SDouglas Gregor case tok::r_square: 811a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 812a686e1b0SDouglas Gregor break; 813a686e1b0SDouglas Gregor 8142b82c2a5SDouglas Gregor case tok::star: 8152b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 8162b82c2a5SDouglas Gregor break; 8172b82c2a5SDouglas Gregor 818718292f2SDouglas Gregor case tok::string_literal: { 819d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 820d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 821d67aea28SRichard Smith HadError = true; 822d67aea28SRichard Smith goto retry; 823d67aea28SRichard Smith } 824d67aea28SRichard Smith 825718292f2SDouglas Gregor // Parse the string literal. 826718292f2SDouglas Gregor LangOptions LangOpts; 827718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 828718292f2SDouglas Gregor if (StringLiteral.hadError) 829718292f2SDouglas Gregor goto retry; 830718292f2SDouglas Gregor 831718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 832718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 833718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 834718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 835718292f2SDouglas Gregor Saved[Length] = 0; 836718292f2SDouglas Gregor 837718292f2SDouglas Gregor // Form the token. 838718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 839718292f2SDouglas Gregor Tok.StringData = Saved; 840718292f2SDouglas Gregor Tok.StringLength = Length; 841718292f2SDouglas Gregor break; 842718292f2SDouglas Gregor } 843718292f2SDouglas Gregor 844718292f2SDouglas Gregor case tok::comment: 845718292f2SDouglas Gregor goto retry; 846718292f2SDouglas Gregor 847718292f2SDouglas Gregor default: 848718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 849718292f2SDouglas Gregor HadError = true; 850718292f2SDouglas Gregor goto retry; 851718292f2SDouglas Gregor } 852718292f2SDouglas Gregor 853718292f2SDouglas Gregor return Result; 854718292f2SDouglas Gregor } 855718292f2SDouglas Gregor 856718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 857718292f2SDouglas Gregor unsigned braceDepth = 0; 858a686e1b0SDouglas Gregor unsigned squareDepth = 0; 859718292f2SDouglas Gregor do { 860718292f2SDouglas Gregor switch (Tok.Kind) { 861718292f2SDouglas Gregor case MMToken::EndOfFile: 862718292f2SDouglas Gregor return; 863718292f2SDouglas Gregor 864718292f2SDouglas Gregor case MMToken::LBrace: 865a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 866718292f2SDouglas Gregor return; 867718292f2SDouglas Gregor 868718292f2SDouglas Gregor ++braceDepth; 869718292f2SDouglas Gregor break; 870718292f2SDouglas Gregor 871a686e1b0SDouglas Gregor case MMToken::LSquare: 872a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 873a686e1b0SDouglas Gregor return; 874a686e1b0SDouglas Gregor 875a686e1b0SDouglas Gregor ++squareDepth; 876a686e1b0SDouglas Gregor break; 877a686e1b0SDouglas Gregor 878718292f2SDouglas Gregor case MMToken::RBrace: 879718292f2SDouglas Gregor if (braceDepth > 0) 880718292f2SDouglas Gregor --braceDepth; 881718292f2SDouglas Gregor else if (Tok.is(K)) 882718292f2SDouglas Gregor return; 883718292f2SDouglas Gregor break; 884718292f2SDouglas Gregor 885a686e1b0SDouglas Gregor case MMToken::RSquare: 886a686e1b0SDouglas Gregor if (squareDepth > 0) 887a686e1b0SDouglas Gregor --squareDepth; 888a686e1b0SDouglas Gregor else if (Tok.is(K)) 889a686e1b0SDouglas Gregor return; 890a686e1b0SDouglas Gregor break; 891a686e1b0SDouglas Gregor 892718292f2SDouglas Gregor default: 893a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 894718292f2SDouglas Gregor return; 895718292f2SDouglas Gregor break; 896718292f2SDouglas Gregor } 897718292f2SDouglas Gregor 898718292f2SDouglas Gregor consumeToken(); 899718292f2SDouglas Gregor } while (true); 900718292f2SDouglas Gregor } 901718292f2SDouglas Gregor 902e7ab3669SDouglas Gregor /// \brief Parse a module-id. 903e7ab3669SDouglas Gregor /// 904e7ab3669SDouglas Gregor /// module-id: 905e7ab3669SDouglas Gregor /// identifier 906e7ab3669SDouglas Gregor /// identifier '.' module-id 907e7ab3669SDouglas Gregor /// 908e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 909e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 910e7ab3669SDouglas Gregor Id.clear(); 911e7ab3669SDouglas Gregor do { 912e7ab3669SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 913e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 914e7ab3669SDouglas Gregor consumeToken(); 915e7ab3669SDouglas Gregor } else { 916e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 917e7ab3669SDouglas Gregor return true; 918e7ab3669SDouglas Gregor } 919e7ab3669SDouglas Gregor 920e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 921e7ab3669SDouglas Gregor break; 922e7ab3669SDouglas Gregor 923e7ab3669SDouglas Gregor consumeToken(); 924e7ab3669SDouglas Gregor } while (true); 925e7ab3669SDouglas Gregor 926e7ab3669SDouglas Gregor return false; 927e7ab3669SDouglas Gregor } 928e7ab3669SDouglas Gregor 929a686e1b0SDouglas Gregor namespace { 930a686e1b0SDouglas Gregor /// \brief Enumerates the known attributes. 931a686e1b0SDouglas Gregor enum AttributeKind { 932a686e1b0SDouglas Gregor /// \brief An unknown attribute. 933a686e1b0SDouglas Gregor AT_unknown, 934a686e1b0SDouglas Gregor /// \brief The 'system' attribute. 935a686e1b0SDouglas Gregor AT_system 936a686e1b0SDouglas Gregor }; 937a686e1b0SDouglas Gregor } 938a686e1b0SDouglas Gregor 939718292f2SDouglas Gregor /// \brief Parse a module declaration. 940718292f2SDouglas Gregor /// 941718292f2SDouglas Gregor /// module-declaration: 942a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 943a686e1b0SDouglas Gregor /// { module-member* } 944a686e1b0SDouglas Gregor /// 945718292f2SDouglas Gregor /// module-member: 9461fb5c3a6SDouglas Gregor /// requires-declaration 947718292f2SDouglas Gregor /// header-declaration 948e7ab3669SDouglas Gregor /// submodule-declaration 9492b82c2a5SDouglas Gregor /// export-declaration 950*6ddfca91SDouglas Gregor /// link-declaration 95173441091SDouglas Gregor /// 95273441091SDouglas Gregor /// submodule-declaration: 95373441091SDouglas Gregor /// module-declaration 95473441091SDouglas Gregor /// inferred-submodule-declaration 955718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 956755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 957755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 958f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 959e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 960718292f2SDouglas Gregor bool Explicit = false; 961f2161a70SDouglas Gregor bool Framework = false; 962755b2055SDouglas Gregor 963f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 964f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 965e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 966f2161a70SDouglas Gregor Explicit = true; 967f2161a70SDouglas Gregor } 968f2161a70SDouglas Gregor 969f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 970755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 971755b2055SDouglas Gregor consumeToken(); 972755b2055SDouglas Gregor Framework = true; 973755b2055SDouglas Gregor } 974718292f2SDouglas Gregor 975718292f2SDouglas Gregor // Parse 'module' keyword. 976718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 977d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 978718292f2SDouglas Gregor consumeToken(); 979718292f2SDouglas Gregor HadError = true; 980718292f2SDouglas Gregor return; 981718292f2SDouglas Gregor } 982718292f2SDouglas Gregor consumeToken(); // 'module' keyword 983718292f2SDouglas Gregor 98473441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 98573441091SDouglas Gregor // Parse it. 98673441091SDouglas Gregor if (Tok.is(MMToken::Star)) 9879194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 98873441091SDouglas Gregor 989718292f2SDouglas Gregor // Parse the module name. 990e7ab3669SDouglas Gregor ModuleId Id; 991e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 992718292f2SDouglas Gregor HadError = true; 993718292f2SDouglas Gregor return; 994718292f2SDouglas Gregor } 995e7ab3669SDouglas Gregor 996e7ab3669SDouglas Gregor if (ActiveModule) { 997e7ab3669SDouglas Gregor if (Id.size() > 1) { 998e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 999e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1000e7ab3669SDouglas Gregor 1001e7ab3669SDouglas Gregor HadError = true; 1002e7ab3669SDouglas Gregor return; 1003e7ab3669SDouglas Gregor } 1004e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1005e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1006e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1007e7ab3669SDouglas Gregor Explicit = false; 1008e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1009e7ab3669SDouglas Gregor HadError = true; 1010e7ab3669SDouglas Gregor } 1011e7ab3669SDouglas Gregor 1012e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1013e7ab3669SDouglas Gregor if (Id.size() > 1) { 1014e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1015e7ab3669SDouglas Gregor // is a submodule. 1016e7ab3669SDouglas Gregor ActiveModule = 0; 1017e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1018e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 1019e7ab3669SDouglas Gregor ActiveModule = Next; 1020e7ab3669SDouglas Gregor continue; 1021e7ab3669SDouglas Gregor } 1022e7ab3669SDouglas Gregor 1023e7ab3669SDouglas Gregor if (ActiveModule) { 1024e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 1025e7ab3669SDouglas Gregor << Id[I].first << ActiveModule->getTopLevelModule(); 1026e7ab3669SDouglas Gregor } else { 1027e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1028e7ab3669SDouglas Gregor } 1029e7ab3669SDouglas Gregor HadError = true; 1030e7ab3669SDouglas Gregor return; 1031e7ab3669SDouglas Gregor } 1032e7ab3669SDouglas Gregor } 1033e7ab3669SDouglas Gregor 1034e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1035e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1036718292f2SDouglas Gregor 1037a686e1b0SDouglas Gregor // Parse the optional attribute list. 10384442605fSBill Wendling Attributes Attrs; 10399194a91dSDouglas Gregor parseOptionalAttributes(Attrs); 1040a686e1b0SDouglas Gregor 1041718292f2SDouglas Gregor // Parse the opening brace. 1042718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1043718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1044718292f2SDouglas Gregor << ModuleName; 1045718292f2SDouglas Gregor HadError = true; 1046718292f2SDouglas Gregor return; 1047718292f2SDouglas Gregor } 1048718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1049718292f2SDouglas Gregor 1050718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 1051eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 1052fcc54a3bSDouglas Gregor if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) { 1053fcc54a3bSDouglas Gregor // Skip the module definition. 1054fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1055fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1056fcc54a3bSDouglas Gregor consumeToken(); 1057fcc54a3bSDouglas Gregor else { 1058fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1059fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1060fcc54a3bSDouglas Gregor HadError = true; 1061fcc54a3bSDouglas Gregor } 1062fcc54a3bSDouglas Gregor return; 1063fcc54a3bSDouglas Gregor } 1064fcc54a3bSDouglas Gregor 1065718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1066718292f2SDouglas Gregor << ModuleName; 1067eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1068718292f2SDouglas Gregor 1069718292f2SDouglas Gregor // Skip the module definition. 1070718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1071718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1072718292f2SDouglas Gregor consumeToken(); 1073718292f2SDouglas Gregor 1074718292f2SDouglas Gregor HadError = true; 1075718292f2SDouglas Gregor return; 1076718292f2SDouglas Gregor } 1077718292f2SDouglas Gregor 1078718292f2SDouglas Gregor // Start defining this module. 1079eb90e830SDouglas Gregor ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, 1080eb90e830SDouglas Gregor Explicit).first; 1081eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 10829194a91dSDouglas Gregor if (Attrs.IsSystem) 1083a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 1084718292f2SDouglas Gregor 1085718292f2SDouglas Gregor bool Done = false; 1086718292f2SDouglas Gregor do { 1087718292f2SDouglas Gregor switch (Tok.Kind) { 1088718292f2SDouglas Gregor case MMToken::EndOfFile: 1089718292f2SDouglas Gregor case MMToken::RBrace: 1090718292f2SDouglas Gregor Done = true; 1091718292f2SDouglas Gregor break; 1092718292f2SDouglas Gregor 1093718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 1094f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1095718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1096718292f2SDouglas Gregor parseModuleDecl(); 1097718292f2SDouglas Gregor break; 1098718292f2SDouglas Gregor 10992b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 11002b82c2a5SDouglas Gregor parseExportDecl(); 11012b82c2a5SDouglas Gregor break; 11022b82c2a5SDouglas Gregor 11031fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 11041fb5c3a6SDouglas Gregor parseRequiresDecl(); 11051fb5c3a6SDouglas Gregor break; 11061fb5c3a6SDouglas Gregor 1107524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 1108524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 1109524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 111059527666SDouglas Gregor parseHeaderDecl(UmbrellaLoc, SourceLocation()); 1111524e33e1SDouglas Gregor else 1112524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 1113718292f2SDouglas Gregor break; 1114524e33e1SDouglas Gregor } 1115718292f2SDouglas Gregor 111659527666SDouglas Gregor case MMToken::ExcludeKeyword: { 111759527666SDouglas Gregor SourceLocation ExcludeLoc = consumeToken(); 111859527666SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) { 111959527666SDouglas Gregor parseHeaderDecl(SourceLocation(), ExcludeLoc); 112059527666SDouglas Gregor } else { 112159527666SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 112259527666SDouglas Gregor << "exclude"; 112359527666SDouglas Gregor } 112459527666SDouglas Gregor break; 112559527666SDouglas Gregor } 112659527666SDouglas Gregor 1127322f633cSDouglas Gregor case MMToken::HeaderKeyword: 112859527666SDouglas Gregor parseHeaderDecl(SourceLocation(), SourceLocation()); 1129718292f2SDouglas Gregor break; 1130718292f2SDouglas Gregor 1131*6ddfca91SDouglas Gregor case MMToken::LinkKeyword: 1132*6ddfca91SDouglas Gregor parseLinkDecl(); 1133*6ddfca91SDouglas Gregor break; 1134*6ddfca91SDouglas Gregor 1135718292f2SDouglas Gregor default: 1136718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 1137718292f2SDouglas Gregor consumeToken(); 1138718292f2SDouglas Gregor break; 1139718292f2SDouglas Gregor } 1140718292f2SDouglas Gregor } while (!Done); 1141718292f2SDouglas Gregor 1142718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1143718292f2SDouglas Gregor consumeToken(); 1144718292f2SDouglas Gregor else { 1145718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1146718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1147718292f2SDouglas Gregor HadError = true; 1148718292f2SDouglas Gregor } 1149718292f2SDouglas Gregor 1150e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 1151e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 1152718292f2SDouglas Gregor } 1153718292f2SDouglas Gregor 11541fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration. 11551fb5c3a6SDouglas Gregor /// 11561fb5c3a6SDouglas Gregor /// requires-declaration: 11571fb5c3a6SDouglas Gregor /// 'requires' feature-list 11581fb5c3a6SDouglas Gregor /// 11591fb5c3a6SDouglas Gregor /// feature-list: 11601fb5c3a6SDouglas Gregor /// identifier ',' feature-list 11611fb5c3a6SDouglas Gregor /// identifier 11621fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 11631fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 11641fb5c3a6SDouglas Gregor 11651fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 11661fb5c3a6SDouglas Gregor consumeToken(); 11671fb5c3a6SDouglas Gregor 11681fb5c3a6SDouglas Gregor // Parse the feature-list. 11691fb5c3a6SDouglas Gregor do { 11701fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 11711fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 11721fb5c3a6SDouglas Gregor HadError = true; 11731fb5c3a6SDouglas Gregor return; 11741fb5c3a6SDouglas Gregor } 11751fb5c3a6SDouglas Gregor 11761fb5c3a6SDouglas Gregor // Consume the feature name. 11771fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 11781fb5c3a6SDouglas Gregor consumeToken(); 11791fb5c3a6SDouglas Gregor 11801fb5c3a6SDouglas Gregor // Add this feature. 118189929282SDouglas Gregor ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target); 11821fb5c3a6SDouglas Gregor 11831fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 11841fb5c3a6SDouglas Gregor break; 11851fb5c3a6SDouglas Gregor 11861fb5c3a6SDouglas Gregor // Consume the comma. 11871fb5c3a6SDouglas Gregor consumeToken(); 11881fb5c3a6SDouglas Gregor } while (true); 11891fb5c3a6SDouglas Gregor } 11901fb5c3a6SDouglas Gregor 1191f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the 1192f2161a70SDouglas Gregor /// subframework in which the given module lives. 1193bf8da9d7SBenjamin Kramer static void appendSubframeworkPaths(Module *Mod, 1194f857950dSDmitri Gribenko SmallVectorImpl<char> &Path) { 1195f2161a70SDouglas Gregor // Collect the framework names from the given module to the top-level module. 1196f857950dSDmitri Gribenko SmallVector<StringRef, 2> Paths; 1197f2161a70SDouglas Gregor for (; Mod; Mod = Mod->Parent) { 1198f2161a70SDouglas Gregor if (Mod->IsFramework) 1199f2161a70SDouglas Gregor Paths.push_back(Mod->Name); 1200f2161a70SDouglas Gregor } 1201f2161a70SDouglas Gregor 1202f2161a70SDouglas Gregor if (Paths.empty()) 1203f2161a70SDouglas Gregor return; 1204f2161a70SDouglas Gregor 1205f2161a70SDouglas Gregor // Add Frameworks/Name.framework for each subframework. 1206f2161a70SDouglas Gregor for (unsigned I = Paths.size() - 1; I != 0; --I) { 1207f2161a70SDouglas Gregor llvm::sys::path::append(Path, "Frameworks"); 1208f2161a70SDouglas Gregor llvm::sys::path::append(Path, Paths[I-1] + ".framework"); 1209f2161a70SDouglas Gregor } 1210f2161a70SDouglas Gregor } 1211f2161a70SDouglas Gregor 12123ec6663bSDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin 12133ec6663bSDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 12143ec6663bSDouglas Gregor /// headers. 12153ec6663bSDouglas Gregor static bool isBuiltinHeader(StringRef FileName) { 12163ec6663bSDouglas Gregor return llvm::StringSwitch<bool>(FileName) 12173ec6663bSDouglas Gregor .Case("float.h", true) 12183ec6663bSDouglas Gregor .Case("iso646.h", true) 12193ec6663bSDouglas Gregor .Case("limits.h", true) 12203ec6663bSDouglas Gregor .Case("stdalign.h", true) 12213ec6663bSDouglas Gregor .Case("stdarg.h", true) 12223ec6663bSDouglas Gregor .Case("stdbool.h", true) 12233ec6663bSDouglas Gregor .Case("stddef.h", true) 12243ec6663bSDouglas Gregor .Case("stdint.h", true) 12253ec6663bSDouglas Gregor .Case("tgmath.h", true) 12263ec6663bSDouglas Gregor .Case("unwind.h", true) 12273ec6663bSDouglas Gregor .Default(false); 12283ec6663bSDouglas Gregor } 12293ec6663bSDouglas Gregor 1230718292f2SDouglas Gregor /// \brief Parse a header declaration. 1231718292f2SDouglas Gregor /// 1232718292f2SDouglas Gregor /// header-declaration: 1233322f633cSDouglas Gregor /// 'umbrella'[opt] 'header' string-literal 123459527666SDouglas Gregor /// 'exclude'[opt] 'header' string-literal 123559527666SDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc, 123659527666SDouglas Gregor SourceLocation ExcludeLoc) { 1237718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 12381871ed3dSBenjamin Kramer consumeToken(); 1239718292f2SDouglas Gregor 1240322f633cSDouglas Gregor bool Umbrella = UmbrellaLoc.isValid(); 124159527666SDouglas Gregor bool Exclude = ExcludeLoc.isValid(); 124259527666SDouglas Gregor assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'"); 1243718292f2SDouglas Gregor // Parse the header name. 1244718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1245718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 1246718292f2SDouglas Gregor << "header"; 1247718292f2SDouglas Gregor HadError = true; 1248718292f2SDouglas Gregor return; 1249718292f2SDouglas Gregor } 1250e7ab3669SDouglas Gregor std::string FileName = Tok.getString(); 1251718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 1252718292f2SDouglas Gregor 1253524e33e1SDouglas Gregor // Check whether we already have an umbrella. 1254524e33e1SDouglas Gregor if (Umbrella && ActiveModule->Umbrella) { 1255524e33e1SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash) 1256524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 1257322f633cSDouglas Gregor HadError = true; 1258322f633cSDouglas Gregor return; 1259322f633cSDouglas Gregor } 1260322f633cSDouglas Gregor 12615257fc63SDouglas Gregor // Look for this file. 1262e7ab3669SDouglas Gregor const FileEntry *File = 0; 12633ec6663bSDouglas Gregor const FileEntry *BuiltinFile = 0; 12642c1dd271SDylan Noblesmith SmallString<128> PathName; 1265e7ab3669SDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 1266e7ab3669SDouglas Gregor PathName = FileName; 1267e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 12687033127bSDouglas Gregor } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) { 12697033127bSDouglas Gregor PathName = Dir->getName(); 12707033127bSDouglas Gregor llvm::sys::path::append(PathName, FileName); 12717033127bSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1272e7ab3669SDouglas Gregor } else { 1273e7ab3669SDouglas Gregor // Search for the header file within the search directory. 12747033127bSDouglas Gregor PathName = Directory->getName(); 1275e7ab3669SDouglas Gregor unsigned PathLength = PathName.size(); 1276755b2055SDouglas Gregor 1277f2161a70SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 1278f2161a70SDouglas Gregor appendSubframeworkPaths(ActiveModule, PathName); 1279755b2055SDouglas Gregor 1280e7ab3669SDouglas Gregor // Check whether this file is in the public headers. 1281e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 12825257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1283e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1284e7ab3669SDouglas Gregor 1285e7ab3669SDouglas Gregor if (!File) { 1286e7ab3669SDouglas Gregor // Check whether this file is in the private headers. 1287e7ab3669SDouglas Gregor PathName.resize(PathLength); 1288e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 1289e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1290e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1291e7ab3669SDouglas Gregor } 1292e7ab3669SDouglas Gregor } else { 1293e7ab3669SDouglas Gregor // Lookup for normal headers. 1294e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1295e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 12963ec6663bSDouglas Gregor 12973ec6663bSDouglas Gregor // If this is a system module with a top-level header, this header 12983ec6663bSDouglas Gregor // may have a counterpart (or replacement) in the set of headers 12993ec6663bSDouglas Gregor // supplied by Clang. Find that builtin header. 13003ec6663bSDouglas Gregor if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir && 13013ec6663bSDouglas Gregor BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) { 13022c1dd271SDylan Noblesmith SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); 13033ec6663bSDouglas Gregor llvm::sys::path::append(BuiltinPathName, FileName); 13043ec6663bSDouglas Gregor BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); 13053ec6663bSDouglas Gregor 13063ec6663bSDouglas Gregor // If Clang supplies this header but the underlying system does not, 13073ec6663bSDouglas Gregor // just silently swap in our builtin version. Otherwise, we'll end 13083ec6663bSDouglas Gregor // up adding both (later). 13093ec6663bSDouglas Gregor if (!File && BuiltinFile) { 13103ec6663bSDouglas Gregor File = BuiltinFile; 13113ec6663bSDouglas Gregor BuiltinFile = 0; 13123ec6663bSDouglas Gregor } 13133ec6663bSDouglas Gregor } 1314e7ab3669SDouglas Gregor } 1315e7ab3669SDouglas Gregor } 13165257fc63SDouglas Gregor 13175257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 13185257fc63SDouglas Gregor // Come up with a lazy way to do this. 1319e7ab3669SDouglas Gregor if (File) { 132059527666SDouglas Gregor if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) { 13215257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 132259527666SDouglas Gregor << FileName << OwningModule.getModule()->getFullModuleName(); 13235257fc63SDouglas Gregor HadError = true; 1324322f633cSDouglas Gregor } else if (Umbrella) { 1325322f633cSDouglas Gregor const DirectoryEntry *UmbrellaDir = File->getDir(); 132659527666SDouglas Gregor if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { 1327322f633cSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 132859527666SDouglas Gregor << UmbrellaModule->getFullModuleName(); 1329322f633cSDouglas Gregor HadError = true; 13305257fc63SDouglas Gregor } else { 1331322f633cSDouglas Gregor // Record this umbrella header. 1332322f633cSDouglas Gregor Map.setUmbrellaHeader(ActiveModule, File); 1333322f633cSDouglas Gregor } 1334322f633cSDouglas Gregor } else { 1335322f633cSDouglas Gregor // Record this header. 133659527666SDouglas Gregor Map.addHeader(ActiveModule, File, Exclude); 13373ec6663bSDouglas Gregor 13383ec6663bSDouglas Gregor // If there is a builtin counterpart to this file, add it now. 13393ec6663bSDouglas Gregor if (BuiltinFile) 134059527666SDouglas Gregor Map.addHeader(ActiveModule, BuiltinFile, Exclude); 13415257fc63SDouglas Gregor } 13424b27a64bSDouglas Gregor } else if (!Exclude) { 13434b27a64bSDouglas Gregor // Ignore excluded header files. They're optional anyway. 13444b27a64bSDouglas Gregor 13455257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 1346524e33e1SDouglas Gregor << Umbrella << FileName; 13475257fc63SDouglas Gregor HadError = true; 13485257fc63SDouglas Gregor } 1349718292f2SDouglas Gregor } 1350718292f2SDouglas Gregor 1351524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration. 1352524e33e1SDouglas Gregor /// 1353524e33e1SDouglas Gregor /// umbrella-dir-declaration: 1354524e33e1SDouglas Gregor /// umbrella string-literal 1355524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 1356524e33e1SDouglas Gregor // Parse the directory name. 1357524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1358524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 1359524e33e1SDouglas Gregor << "umbrella"; 1360524e33e1SDouglas Gregor HadError = true; 1361524e33e1SDouglas Gregor return; 1362524e33e1SDouglas Gregor } 1363524e33e1SDouglas Gregor 1364524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 1365524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 1366524e33e1SDouglas Gregor 1367524e33e1SDouglas Gregor // Check whether we already have an umbrella. 1368524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 1369524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 1370524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 1371524e33e1SDouglas Gregor HadError = true; 1372524e33e1SDouglas Gregor return; 1373524e33e1SDouglas Gregor } 1374524e33e1SDouglas Gregor 1375524e33e1SDouglas Gregor // Look for this file. 1376524e33e1SDouglas Gregor const DirectoryEntry *Dir = 0; 1377524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 1378524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 1379524e33e1SDouglas Gregor else { 13802c1dd271SDylan Noblesmith SmallString<128> PathName; 1381524e33e1SDouglas Gregor PathName = Directory->getName(); 1382524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 1383524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 1384524e33e1SDouglas Gregor } 1385524e33e1SDouglas Gregor 1386524e33e1SDouglas Gregor if (!Dir) { 1387524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found) 1388524e33e1SDouglas Gregor << DirName; 1389524e33e1SDouglas Gregor HadError = true; 1390524e33e1SDouglas Gregor return; 1391524e33e1SDouglas Gregor } 1392524e33e1SDouglas Gregor 1393524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 1394524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 1395524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 1396524e33e1SDouglas Gregor HadError = true; 1397524e33e1SDouglas Gregor return; 1398524e33e1SDouglas Gregor } 1399524e33e1SDouglas Gregor 1400524e33e1SDouglas Gregor // Record this umbrella directory. 1401524e33e1SDouglas Gregor Map.setUmbrellaDir(ActiveModule, Dir); 1402524e33e1SDouglas Gregor } 1403524e33e1SDouglas Gregor 14042b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 14052b82c2a5SDouglas Gregor /// 14062b82c2a5SDouglas Gregor /// export-declaration: 14072b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 14082b82c2a5SDouglas Gregor /// 14092b82c2a5SDouglas Gregor /// wildcard-module-id: 14102b82c2a5SDouglas Gregor /// identifier 14112b82c2a5SDouglas Gregor /// '*' 14122b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 14132b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 14142b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 14152b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 14162b82c2a5SDouglas Gregor 14172b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 14182b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 14192b82c2a5SDouglas Gregor bool Wildcard = false; 14202b82c2a5SDouglas Gregor do { 14212b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 14222b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 14232b82c2a5SDouglas Gregor Tok.getLocation())); 14242b82c2a5SDouglas Gregor consumeToken(); 14252b82c2a5SDouglas Gregor 14262b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 14272b82c2a5SDouglas Gregor consumeToken(); 14282b82c2a5SDouglas Gregor continue; 14292b82c2a5SDouglas Gregor } 14302b82c2a5SDouglas Gregor 14312b82c2a5SDouglas Gregor break; 14322b82c2a5SDouglas Gregor } 14332b82c2a5SDouglas Gregor 14342b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 14352b82c2a5SDouglas Gregor Wildcard = true; 1436f5eedd05SDouglas Gregor consumeToken(); 14372b82c2a5SDouglas Gregor break; 14382b82c2a5SDouglas Gregor } 14392b82c2a5SDouglas Gregor 14402b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 14412b82c2a5SDouglas Gregor HadError = true; 14422b82c2a5SDouglas Gregor return; 14432b82c2a5SDouglas Gregor } while (true); 14442b82c2a5SDouglas Gregor 14452b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 14462b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 14472b82c2a5SDouglas Gregor }; 14482b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 14492b82c2a5SDouglas Gregor } 14502b82c2a5SDouglas Gregor 1451*6ddfca91SDouglas Gregor /// \brief Parse a link declaration. 1452*6ddfca91SDouglas Gregor /// 1453*6ddfca91SDouglas Gregor /// module-declaration: 1454*6ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 1455*6ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 1456*6ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 1457*6ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 1458*6ddfca91SDouglas Gregor 1459*6ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 1460*6ddfca91SDouglas Gregor bool IsFramework = false; 1461*6ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 1462*6ddfca91SDouglas Gregor consumeToken(); 1463*6ddfca91SDouglas Gregor IsFramework = true; 1464*6ddfca91SDouglas Gregor } 1465*6ddfca91SDouglas Gregor 1466*6ddfca91SDouglas Gregor // Parse the library name 1467*6ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1468*6ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 1469*6ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 1470*6ddfca91SDouglas Gregor HadError = true; 1471*6ddfca91SDouglas Gregor return; 1472*6ddfca91SDouglas Gregor } 1473*6ddfca91SDouglas Gregor 1474*6ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 1475*6ddfca91SDouglas Gregor consumeToken(); 1476*6ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 1477*6ddfca91SDouglas Gregor IsFramework)); 1478*6ddfca91SDouglas Gregor } 1479*6ddfca91SDouglas Gregor 1480*6ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules). 14819194a91dSDouglas Gregor /// 14829194a91dSDouglas Gregor /// module-declaration: 14839194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 14849194a91dSDouglas Gregor /// { inferred-module-member* } 14859194a91dSDouglas Gregor /// 14869194a91dSDouglas Gregor /// inferred-module-member: 14879194a91dSDouglas Gregor /// 'export' '*' 14889194a91dSDouglas Gregor /// 'exclude' identifier 14899194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 149073441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 149173441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 149273441091SDouglas Gregor bool Failed = false; 149373441091SDouglas Gregor 149473441091SDouglas Gregor // Inferred modules must be submodules. 14959194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 149673441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 149773441091SDouglas Gregor Failed = true; 149873441091SDouglas Gregor } 149973441091SDouglas Gregor 15009194a91dSDouglas Gregor if (ActiveModule) { 1501524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 1502524e33e1SDouglas Gregor if (!Failed && !ActiveModule->getUmbrellaDir()) { 150373441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 150473441091SDouglas Gregor Failed = true; 150573441091SDouglas Gregor } 150673441091SDouglas Gregor 150773441091SDouglas Gregor // Check for redefinition of an inferred module. 1508dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 150973441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 1510dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 1511dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 151273441091SDouglas Gregor diag::note_mmap_prev_definition); 151373441091SDouglas Gregor Failed = true; 151473441091SDouglas Gregor } 151573441091SDouglas Gregor 15169194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 15179194a91dSDouglas Gregor if (Framework) { 15189194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 15199194a91dSDouglas Gregor Framework = false; 15209194a91dSDouglas Gregor } 15219194a91dSDouglas Gregor } else if (Explicit) { 15229194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 15239194a91dSDouglas Gregor Explicit = false; 15249194a91dSDouglas Gregor } 15259194a91dSDouglas Gregor 152673441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 152773441091SDouglas Gregor if (Failed) { 152873441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 152973441091SDouglas Gregor consumeToken(); 153073441091SDouglas Gregor skipUntil(MMToken::RBrace); 153173441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 153273441091SDouglas Gregor consumeToken(); 153373441091SDouglas Gregor } 153473441091SDouglas Gregor HadError = true; 153573441091SDouglas Gregor return; 153673441091SDouglas Gregor } 153773441091SDouglas Gregor 15389194a91dSDouglas Gregor // Parse optional attributes. 15394442605fSBill Wendling Attributes Attrs; 15409194a91dSDouglas Gregor parseOptionalAttributes(Attrs); 15419194a91dSDouglas Gregor 15429194a91dSDouglas Gregor if (ActiveModule) { 154373441091SDouglas Gregor // Note that we have an inferred submodule. 1544dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 1545dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 1546dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 15479194a91dSDouglas Gregor } else { 15489194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 15499194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 15509194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem; 15519194a91dSDouglas Gregor } 155273441091SDouglas Gregor 155373441091SDouglas Gregor // Parse the opening brace. 155473441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 155573441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 155673441091SDouglas Gregor HadError = true; 155773441091SDouglas Gregor return; 155873441091SDouglas Gregor } 155973441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 156073441091SDouglas Gregor 156173441091SDouglas Gregor // Parse the body of the inferred submodule. 156273441091SDouglas Gregor bool Done = false; 156373441091SDouglas Gregor do { 156473441091SDouglas Gregor switch (Tok.Kind) { 156573441091SDouglas Gregor case MMToken::EndOfFile: 156673441091SDouglas Gregor case MMToken::RBrace: 156773441091SDouglas Gregor Done = true; 156873441091SDouglas Gregor break; 156973441091SDouglas Gregor 15709194a91dSDouglas Gregor case MMToken::ExcludeKeyword: { 15719194a91dSDouglas Gregor if (ActiveModule) { 15729194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 1573162405daSDouglas Gregor << (ActiveModule != 0); 15749194a91dSDouglas Gregor consumeToken(); 15759194a91dSDouglas Gregor break; 15769194a91dSDouglas Gregor } 15779194a91dSDouglas Gregor 15789194a91dSDouglas Gregor consumeToken(); 15799194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 15809194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 15819194a91dSDouglas Gregor break; 15829194a91dSDouglas Gregor } 15839194a91dSDouglas Gregor 15849194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 15859194a91dSDouglas Gregor .push_back(Tok.getString()); 15869194a91dSDouglas Gregor consumeToken(); 15879194a91dSDouglas Gregor break; 15889194a91dSDouglas Gregor } 15899194a91dSDouglas Gregor 15909194a91dSDouglas Gregor case MMToken::ExportKeyword: 15919194a91dSDouglas Gregor if (!ActiveModule) { 15929194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 1593162405daSDouglas Gregor << (ActiveModule != 0); 15949194a91dSDouglas Gregor consumeToken(); 15959194a91dSDouglas Gregor break; 15969194a91dSDouglas Gregor } 15979194a91dSDouglas Gregor 159873441091SDouglas Gregor consumeToken(); 159973441091SDouglas Gregor if (Tok.is(MMToken::Star)) 1600dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 160173441091SDouglas Gregor else 160273441091SDouglas Gregor Diags.Report(Tok.getLocation(), 160373441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 160473441091SDouglas Gregor consumeToken(); 160573441091SDouglas Gregor break; 160673441091SDouglas Gregor 160773441091SDouglas Gregor case MMToken::ExplicitKeyword: 160873441091SDouglas Gregor case MMToken::ModuleKeyword: 160973441091SDouglas Gregor case MMToken::HeaderKeyword: 161073441091SDouglas Gregor case MMToken::UmbrellaKeyword: 161173441091SDouglas Gregor default: 16129194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 1613162405daSDouglas Gregor << (ActiveModule != 0); 161473441091SDouglas Gregor consumeToken(); 161573441091SDouglas Gregor break; 161673441091SDouglas Gregor } 161773441091SDouglas Gregor } while (!Done); 161873441091SDouglas Gregor 161973441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 162073441091SDouglas Gregor consumeToken(); 162173441091SDouglas Gregor else { 162273441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 162373441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 162473441091SDouglas Gregor HadError = true; 162573441091SDouglas Gregor } 162673441091SDouglas Gregor } 162773441091SDouglas Gregor 16289194a91dSDouglas Gregor /// \brief Parse optional attributes. 16299194a91dSDouglas Gregor /// 16309194a91dSDouglas Gregor /// attributes: 16319194a91dSDouglas Gregor /// attribute attributes 16329194a91dSDouglas Gregor /// attribute 16339194a91dSDouglas Gregor /// 16349194a91dSDouglas Gregor /// attribute: 16359194a91dSDouglas Gregor /// [ identifier ] 16369194a91dSDouglas Gregor /// 16379194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 16389194a91dSDouglas Gregor /// 16399194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 16404442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 16419194a91dSDouglas Gregor bool HadError = false; 16429194a91dSDouglas Gregor 16439194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 16449194a91dSDouglas Gregor // Consume the '['. 16459194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 16469194a91dSDouglas Gregor 16479194a91dSDouglas Gregor // Check whether we have an attribute name here. 16489194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 16499194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 16509194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 16519194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 16529194a91dSDouglas Gregor consumeToken(); 16539194a91dSDouglas Gregor HadError = true; 16549194a91dSDouglas Gregor } 16559194a91dSDouglas Gregor 16569194a91dSDouglas Gregor // Decode the attribute name. 16579194a91dSDouglas Gregor AttributeKind Attribute 16589194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 16599194a91dSDouglas Gregor .Case("system", AT_system) 16609194a91dSDouglas Gregor .Default(AT_unknown); 16619194a91dSDouglas Gregor switch (Attribute) { 16629194a91dSDouglas Gregor case AT_unknown: 16639194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 16649194a91dSDouglas Gregor << Tok.getString(); 16659194a91dSDouglas Gregor break; 16669194a91dSDouglas Gregor 16679194a91dSDouglas Gregor case AT_system: 16689194a91dSDouglas Gregor Attrs.IsSystem = true; 16699194a91dSDouglas Gregor break; 16709194a91dSDouglas Gregor } 16719194a91dSDouglas Gregor consumeToken(); 16729194a91dSDouglas Gregor 16739194a91dSDouglas Gregor // Consume the ']'. 16749194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 16759194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 16769194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 16779194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 16789194a91dSDouglas Gregor HadError = true; 16799194a91dSDouglas Gregor } 16809194a91dSDouglas Gregor 16819194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 16829194a91dSDouglas Gregor consumeToken(); 16839194a91dSDouglas Gregor } 16849194a91dSDouglas Gregor 16859194a91dSDouglas Gregor return HadError; 16869194a91dSDouglas Gregor } 16879194a91dSDouglas Gregor 16887033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence 16897033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null. 16907033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() { 16917033127bSDouglas Gregor for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) { 16927033127bSDouglas Gregor // If we have an umbrella directory, use that. 16937033127bSDouglas Gregor if (Mod->hasUmbrellaDir()) 16947033127bSDouglas Gregor return Mod->getUmbrellaDir(); 16957033127bSDouglas Gregor 16967033127bSDouglas Gregor // If we have a framework directory, stop looking. 16977033127bSDouglas Gregor if (Mod->IsFramework) 16987033127bSDouglas Gregor return 0; 16997033127bSDouglas Gregor } 17007033127bSDouglas Gregor 17017033127bSDouglas Gregor return 0; 17027033127bSDouglas Gregor } 17037033127bSDouglas Gregor 1704718292f2SDouglas Gregor /// \brief Parse a module map file. 1705718292f2SDouglas Gregor /// 1706718292f2SDouglas Gregor /// module-map-file: 1707718292f2SDouglas Gregor /// module-declaration* 1708718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 1709718292f2SDouglas Gregor do { 1710718292f2SDouglas Gregor switch (Tok.Kind) { 1711718292f2SDouglas Gregor case MMToken::EndOfFile: 1712718292f2SDouglas Gregor return HadError; 1713718292f2SDouglas Gregor 1714e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 1715718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1716755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 1717718292f2SDouglas Gregor parseModuleDecl(); 1718718292f2SDouglas Gregor break; 1719718292f2SDouglas Gregor 17201fb5c3a6SDouglas Gregor case MMToken::Comma: 172159527666SDouglas Gregor case MMToken::ExcludeKeyword: 17222b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 1723718292f2SDouglas Gregor case MMToken::HeaderKeyword: 1724718292f2SDouglas Gregor case MMToken::Identifier: 1725718292f2SDouglas Gregor case MMToken::LBrace: 1726*6ddfca91SDouglas Gregor case MMToken::LinkKeyword: 1727a686e1b0SDouglas Gregor case MMToken::LSquare: 17282b82c2a5SDouglas Gregor case MMToken::Period: 1729718292f2SDouglas Gregor case MMToken::RBrace: 1730a686e1b0SDouglas Gregor case MMToken::RSquare: 17311fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 17322b82c2a5SDouglas Gregor case MMToken::Star: 1733718292f2SDouglas Gregor case MMToken::StringLiteral: 1734718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 1735718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1736718292f2SDouglas Gregor HadError = true; 1737718292f2SDouglas Gregor consumeToken(); 1738718292f2SDouglas Gregor break; 1739718292f2SDouglas Gregor } 1740718292f2SDouglas Gregor } while (true); 1741718292f2SDouglas Gregor } 1742718292f2SDouglas Gregor 1743718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 17444ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 17454ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 17464ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 17474ddf2221SDouglas Gregor return Known->second; 17484ddf2221SDouglas Gregor 174989929282SDouglas Gregor assert(Target != 0 && "Missing target information"); 1750718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 1751718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 1752718292f2SDouglas Gregor if (!Buffer) 17534ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 1754718292f2SDouglas Gregor 1755718292f2SDouglas Gregor // Parse this module map file. 17561fb5c3a6SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts); 17571fb5c3a6SDouglas Gregor Diags->getClient()->BeginSourceFile(MMapLangOpts); 1758bc10b9fbSDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(), 17593ec6663bSDouglas Gregor BuiltinIncludeDir); 1760718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 1761718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 17624ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 1763718292f2SDouglas Gregor return Result; 1764718292f2SDouglas Gregor } 1765