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" 15a7d03840SJordan Rose #include "clang/Basic/CharInfo.h" 16718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h" 17811db4eaSDouglas Gregor #include "clang/Basic/DiagnosticOptions.h" 18718292f2SDouglas Gregor #include "clang/Basic/FileManager.h" 19718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h" 20718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h" 21b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h" 223a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h" 233a02247dSChandler Carruth #include "clang/Lex/Lexer.h" 243a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h" 253a02247dSChandler Carruth #include "llvm/ADT/StringRef.h" 263a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h" 27718292f2SDouglas Gregor #include "llvm/Support/Allocator.h" 28e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h" 29718292f2SDouglas Gregor #include "llvm/Support/Host.h" 305257fc63SDouglas Gregor #include "llvm/Support/PathV2.h" 31718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 3207c22b78SDouglas Gregor #include <stdlib.h> 3301c7cfa2SDouglas Gregor #if defined(LLVM_ON_UNIX) 34eadae014SDmitri Gribenko #include <limits.h> 3501c7cfa2SDouglas Gregor #endif 36718292f2SDouglas Gregor using namespace clang; 37718292f2SDouglas Gregor 382b82c2a5SDouglas Gregor Module::ExportDecl 392b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 402b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 41e4412640SArgyrios Kyrtzidis bool Complain) const { 42f5eedd05SDouglas Gregor // We may have just a wildcard. 43f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 44f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 45f5eedd05SDouglas Gregor return Module::ExportDecl(0, true); 46f5eedd05SDouglas Gregor } 47f5eedd05SDouglas Gregor 48*fb912657SDouglas Gregor // Resolve the module-id. 49*fb912657SDouglas Gregor Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain); 50*fb912657SDouglas Gregor if (!Context) 51*fb912657SDouglas Gregor return Module::ExportDecl(); 52*fb912657SDouglas Gregor 53*fb912657SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 54*fb912657SDouglas Gregor } 55*fb912657SDouglas Gregor 56*fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, 57*fb912657SDouglas Gregor bool Complain) const { 582b82c2a5SDouglas Gregor // Find the starting module. 59*fb912657SDouglas Gregor Module *Context = lookupModuleUnqualified(Id[0].first, Mod); 602b82c2a5SDouglas Gregor if (!Context) { 612b82c2a5SDouglas Gregor if (Complain) 62*fb912657SDouglas Gregor Diags->Report(Id[0].second, diag::err_mmap_missing_module_unqualified) 63*fb912657SDouglas Gregor << Id[0].first << Mod->getFullModuleName(); 642b82c2a5SDouglas Gregor 65*fb912657SDouglas Gregor return 0; 662b82c2a5SDouglas Gregor } 672b82c2a5SDouglas Gregor 682b82c2a5SDouglas Gregor // Dig into the module path. 69*fb912657SDouglas Gregor for (unsigned I = 1, N = Id.size(); I != N; ++I) { 70*fb912657SDouglas Gregor Module *Sub = lookupModuleQualified(Id[I].first, Context); 712b82c2a5SDouglas Gregor if (!Sub) { 722b82c2a5SDouglas Gregor if (Complain) 73*fb912657SDouglas Gregor Diags->Report(Id[I].second, diag::err_mmap_missing_module_qualified) 74*fb912657SDouglas Gregor << Id[I].first << Context->getFullModuleName() 75*fb912657SDouglas Gregor << SourceRange(Id[0].second, Id[I-1].second); 762b82c2a5SDouglas Gregor 77*fb912657SDouglas Gregor return 0; 782b82c2a5SDouglas Gregor } 792b82c2a5SDouglas Gregor 802b82c2a5SDouglas Gregor Context = Sub; 812b82c2a5SDouglas Gregor } 822b82c2a5SDouglas Gregor 83*fb912657SDouglas Gregor return Context; 842b82c2a5SDouglas Gregor } 852b82c2a5SDouglas Gregor 861fb5c3a6SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, 87b146baabSArgyrios Kyrtzidis const LangOptions &LangOpts, const TargetInfo *Target, 88b146baabSArgyrios Kyrtzidis HeaderSearch &HeaderInfo) 89b146baabSArgyrios Kyrtzidis : LangOpts(LangOpts), Target(Target), HeaderInfo(HeaderInfo), 90b146baabSArgyrios Kyrtzidis BuiltinIncludeDir(0) 911fb5c3a6SDouglas Gregor { 92c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 93c95d8192SDylan Noblesmith Diags = IntrusiveRefCntPtr<DiagnosticsEngine>( 94811db4eaSDouglas Gregor new DiagnosticsEngine(DiagIDs, new DiagnosticOptions)); 95718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 96718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 97718292f2SDouglas Gregor } 98718292f2SDouglas Gregor 99718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 1005acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 1015acdf59eSDouglas Gregor IEnd = Modules.end(); 1025acdf59eSDouglas Gregor I != IEnd; ++I) { 1035acdf59eSDouglas Gregor delete I->getValue(); 1045acdf59eSDouglas Gregor } 1055acdf59eSDouglas Gregor 106718292f2SDouglas Gregor delete SourceMgr; 107718292f2SDouglas Gregor } 108718292f2SDouglas Gregor 10989929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 11089929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 11189929282SDouglas Gregor "Improper target override"); 11289929282SDouglas Gregor this->Target = &Target; 11389929282SDouglas Gregor } 11489929282SDouglas Gregor 115056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier. 116056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name, 117056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) { 118056396aeSDouglas Gregor if (Name.empty()) 119056396aeSDouglas Gregor return Name; 120056396aeSDouglas Gregor 121a7d03840SJordan Rose if (!isValidIdentifier(Name)) { 122056396aeSDouglas Gregor // If we don't already have something with the form of an identifier, 123056396aeSDouglas Gregor // create a buffer with the sanitized name. 124056396aeSDouglas Gregor Buffer.clear(); 125a7d03840SJordan Rose if (isDigit(Name[0])) 126056396aeSDouglas Gregor Buffer.push_back('_'); 127056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size()); 128056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 129a7d03840SJordan Rose if (isIdentifierBody(Name[I])) 130056396aeSDouglas Gregor Buffer.push_back(Name[I]); 131056396aeSDouglas Gregor else 132056396aeSDouglas Gregor Buffer.push_back('_'); 133056396aeSDouglas Gregor } 134056396aeSDouglas Gregor 135056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 136056396aeSDouglas Gregor } 137056396aeSDouglas Gregor 138056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name) 139056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) 140056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) 141056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def" 142056396aeSDouglas Gregor .Default(false)) { 143056396aeSDouglas Gregor if (Name.data() != Buffer.data()) 144056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end()); 145056396aeSDouglas Gregor Buffer.push_back('_'); 146056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 147056396aeSDouglas Gregor } 148056396aeSDouglas Gregor 149056396aeSDouglas Gregor return Name; 150056396aeSDouglas Gregor } 151056396aeSDouglas Gregor 152de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 15359527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 1541fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 15559527666SDouglas Gregor // If a header is not available, don't report that it maps to anything. 15659527666SDouglas Gregor if (!Known->second.isAvailable()) 1571fb5c3a6SDouglas Gregor return 0; 1581fb5c3a6SDouglas Gregor 15959527666SDouglas Gregor return Known->second.getModule(); 1601fb5c3a6SDouglas Gregor } 161ab0c8a84SDouglas Gregor 162b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 163f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 164e00c8b20SDouglas Gregor 16574260502SDouglas Gregor // Note: as an egregious but useful hack we use the real path here, because 16674260502SDouglas Gregor // frameworks moving from top-level frameworks to embedded frameworks tend 16774260502SDouglas Gregor // to be symlinked from the top-level location to the embedded location, 16874260502SDouglas Gregor // and we need to resolve lookups as if we had found the embedded location. 169e00c8b20SDouglas Gregor StringRef DirName = SourceMgr->getFileManager().getCanonicalName(Dir); 170a89c5ac4SDouglas Gregor 171a89c5ac4SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 172a89c5ac4SDouglas Gregor // an umbrella header. 173b65dbfffSDouglas Gregor do { 174a89c5ac4SDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 175a89c5ac4SDouglas Gregor = UmbrellaDirs.find(Dir); 176a89c5ac4SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 177a89c5ac4SDouglas Gregor Module *Result = KnownDir->second; 178930a85ccSDouglas Gregor 179930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 18073141fa9SDouglas Gregor // directory. 181930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 18273141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 183930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 184930a85ccSDouglas Gregor 185930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 186a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 187a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 188a89c5ac4SDouglas Gregor // the actual header is located. 1899458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 1909458f82dSDouglas Gregor 1917033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 192a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 193056396aeSDouglas Gregor SmallString<32> NameBuf; 194056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 195056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 196056396aeSDouglas Gregor NameBuf); 197a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 1989458f82dSDouglas Gregor Explicit).first; 199a89c5ac4SDouglas Gregor 200a89c5ac4SDouglas Gregor // Associate the module and the directory. 201a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 202a89c5ac4SDouglas Gregor 203a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 204a89c5ac4SDouglas Gregor // wildcard to the set of exports. 205930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 206a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 207a89c5ac4SDouglas Gregor } 208a89c5ac4SDouglas Gregor 209a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 210056396aeSDouglas Gregor SmallString<32> NameBuf; 211056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 212056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 213a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 2149458f82dSDouglas Gregor Explicit).first; 2153c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 216a89c5ac4SDouglas Gregor 217a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 218a89c5ac4SDouglas Gregor // wildcard to the set of exports. 219930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 220a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 221a89c5ac4SDouglas Gregor } else { 222a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 223a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 224a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 225a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 226a89c5ac4SDouglas Gregor } 227a89c5ac4SDouglas Gregor 22859527666SDouglas Gregor Headers[File] = KnownHeader(Result, /*Excluded=*/false); 2291fb5c3a6SDouglas Gregor 2301fb5c3a6SDouglas Gregor // If a header corresponds to an unavailable module, don't report 2311fb5c3a6SDouglas Gregor // that it maps to anything. 2321fb5c3a6SDouglas Gregor if (!Result->isAvailable()) 2331fb5c3a6SDouglas Gregor return 0; 2341fb5c3a6SDouglas Gregor 235a89c5ac4SDouglas Gregor return Result; 236a89c5ac4SDouglas Gregor } 237a89c5ac4SDouglas Gregor 238a89c5ac4SDouglas Gregor SkippedDirs.push_back(Dir); 239a89c5ac4SDouglas Gregor 240b65dbfffSDouglas Gregor // Retrieve our parent path. 241b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 242b65dbfffSDouglas Gregor if (DirName.empty()) 243b65dbfffSDouglas Gregor break; 244b65dbfffSDouglas Gregor 245b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 246b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 247a89c5ac4SDouglas Gregor } while (Dir); 248b65dbfffSDouglas Gregor 249ab0c8a84SDouglas Gregor return 0; 250ab0c8a84SDouglas Gregor } 251ab0c8a84SDouglas Gregor 252e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 253e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 2541fb5c3a6SDouglas Gregor if (Known != Headers.end()) 25559527666SDouglas Gregor return !Known->second.isAvailable(); 2561fb5c3a6SDouglas Gregor 2571fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 258f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 2591fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 2601fb5c3a6SDouglas Gregor 2611fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 2621fb5c3a6SDouglas Gregor // an umbrella header. 2631fb5c3a6SDouglas Gregor do { 264e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 2651fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 2661fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 2671fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 2681fb5c3a6SDouglas Gregor if (!Found->isAvailable()) 2691fb5c3a6SDouglas Gregor return true; 2701fb5c3a6SDouglas Gregor 2711fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 2721fb5c3a6SDouglas Gregor // directory. 2731fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 2741fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 2751fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 2761fb5c3a6SDouglas Gregor 2771fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 2781fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 2791fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 280056396aeSDouglas Gregor SmallString<32> NameBuf; 281056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 282056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 283056396aeSDouglas Gregor NameBuf); 2841fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 2851fb5c3a6SDouglas Gregor if (!Found) 2861fb5c3a6SDouglas Gregor return false; 2871fb5c3a6SDouglas Gregor if (!Found->isAvailable()) 2881fb5c3a6SDouglas Gregor return true; 2891fb5c3a6SDouglas Gregor } 2901fb5c3a6SDouglas Gregor 2911fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 292056396aeSDouglas Gregor SmallString<32> NameBuf; 293056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 294056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 295056396aeSDouglas Gregor NameBuf); 2961fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 2971fb5c3a6SDouglas Gregor if (!Found) 2981fb5c3a6SDouglas Gregor return false; 2991fb5c3a6SDouglas Gregor } 3001fb5c3a6SDouglas Gregor 3011fb5c3a6SDouglas Gregor return !Found->isAvailable(); 3021fb5c3a6SDouglas Gregor } 3031fb5c3a6SDouglas Gregor 3041fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 3051fb5c3a6SDouglas Gregor 3061fb5c3a6SDouglas Gregor // Retrieve our parent path. 3071fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 3081fb5c3a6SDouglas Gregor if (DirName.empty()) 3091fb5c3a6SDouglas Gregor break; 3101fb5c3a6SDouglas Gregor 3111fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 3121fb5c3a6SDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 3131fb5c3a6SDouglas Gregor } while (Dir); 3141fb5c3a6SDouglas Gregor 3151fb5c3a6SDouglas Gregor return false; 3161fb5c3a6SDouglas Gregor } 3171fb5c3a6SDouglas Gregor 318e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 319e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 32088bdfb0eSDouglas Gregor if (Known != Modules.end()) 32188bdfb0eSDouglas Gregor return Known->getValue(); 32288bdfb0eSDouglas Gregor 32388bdfb0eSDouglas Gregor return 0; 32488bdfb0eSDouglas Gregor } 32588bdfb0eSDouglas Gregor 326e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 327e4412640SArgyrios Kyrtzidis Module *Context) const { 3282b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 3292b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 3302b82c2a5SDouglas Gregor return Sub; 3312b82c2a5SDouglas Gregor } 3322b82c2a5SDouglas Gregor 3332b82c2a5SDouglas Gregor return findModule(Name); 3342b82c2a5SDouglas Gregor } 3352b82c2a5SDouglas Gregor 336e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 3372b82c2a5SDouglas Gregor if (!Context) 3382b82c2a5SDouglas Gregor return findModule(Name); 3392b82c2a5SDouglas Gregor 340eb90e830SDouglas Gregor return Context->findSubmodule(Name); 3412b82c2a5SDouglas Gregor } 3422b82c2a5SDouglas Gregor 343de3ef502SDouglas Gregor std::pair<Module *, bool> 34469021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 34569021974SDouglas Gregor bool IsExplicit) { 34669021974SDouglas Gregor // Try to find an existing module with this name. 347eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 348eb90e830SDouglas Gregor return std::make_pair(Sub, false); 34969021974SDouglas Gregor 35069021974SDouglas Gregor // Create a new module with this name. 35169021974SDouglas Gregor Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 35269021974SDouglas Gregor IsExplicit); 353eb90e830SDouglas Gregor if (!Parent) 35469021974SDouglas Gregor Modules[Name] = Result; 35569021974SDouglas Gregor return std::make_pair(Result, true); 35669021974SDouglas Gregor } 35769021974SDouglas Gregor 3589194a91dSDouglas Gregor bool ModuleMap::canInferFrameworkModule(const DirectoryEntry *ParentDir, 359e4412640SArgyrios Kyrtzidis StringRef Name, bool &IsSystem) const { 3609194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 3619194a91dSDouglas Gregor // for a module map. 362e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 3639194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 3649194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 3659194a91dSDouglas Gregor return false; 3669194a91dSDouglas Gregor 3679194a91dSDouglas Gregor if (!inferred->second.InferModules) 3689194a91dSDouglas Gregor return false; 3699194a91dSDouglas Gregor 3709194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 3719194a91dSDouglas Gregor // to infer this particular module. 3729194a91dSDouglas Gregor bool canInfer = std::find(inferred->second.ExcludedModules.begin(), 3739194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 3749194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 3759194a91dSDouglas Gregor 3769194a91dSDouglas Gregor if (canInfer && inferred->second.InferSystemModules) 3779194a91dSDouglas Gregor IsSystem = true; 3789194a91dSDouglas Gregor 3799194a91dSDouglas Gregor return canInfer; 3809194a91dSDouglas Gregor } 3819194a91dSDouglas Gregor 38211dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we 38311dfe6feSDouglas Gregor /// should link. 38411dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 38511dfe6feSDouglas Gregor FileManager &FileMgr) { 38611dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 38711dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 38811dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 38911dfe6feSDouglas Gregor 39011dfe6feSDouglas Gregor SmallString<128> LibName; 39111dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 39211dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 39311dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 39411dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 39511dfe6feSDouglas Gregor /*IsFramework=*/true)); 39611dfe6feSDouglas Gregor } 39711dfe6feSDouglas Gregor } 39811dfe6feSDouglas Gregor 399de3ef502SDouglas Gregor Module * 40056c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 401e89dbc1dSDouglas Gregor const DirectoryEntry *FrameworkDir, 402a686e1b0SDouglas Gregor bool IsSystem, 403e89dbc1dSDouglas Gregor Module *Parent) { 40456c64013SDouglas Gregor // Check whether we've already found this module. 405e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 406e89dbc1dSDouglas Gregor return Mod; 407e89dbc1dSDouglas Gregor 408e89dbc1dSDouglas Gregor FileManager &FileMgr = SourceMgr->getFileManager(); 40956c64013SDouglas Gregor 4109194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 4119194a91dSDouglas Gregor // a framework module, do so. 4129194a91dSDouglas Gregor if (!Parent) { 4134ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 414e00c8b20SDouglas Gregor 4154ddf2221SDouglas Gregor // Note: as an egregious but useful hack we use the real path here, because 4164ddf2221SDouglas Gregor // we might be looking at an embedded framework that symlinks out to a 4174ddf2221SDouglas Gregor // top-level framework, and we need to infer as if we were naming the 4184ddf2221SDouglas Gregor // top-level framework. 419e00c8b20SDouglas Gregor StringRef FrameworkDirName 420e00c8b20SDouglas Gregor = SourceMgr->getFileManager().getCanonicalName(FrameworkDir); 4214ddf2221SDouglas Gregor 4229194a91dSDouglas Gregor bool canInfer = false; 4234ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 4249194a91dSDouglas Gregor // Figure out the parent path. 4254ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 4269194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 4279194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 4289194a91dSDouglas Gregor // for a module map. 429e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 4309194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 4319194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 4329194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 4339194a91dSDouglas Gregor // one. 4349194a91dSDouglas Gregor SmallString<128> ModMapPath = Parent; 4359194a91dSDouglas Gregor llvm::sys::path::append(ModMapPath, "module.map"); 4369194a91dSDouglas Gregor if (const FileEntry *ModMapFile = FileMgr.getFile(ModMapPath)) { 4379194a91dSDouglas Gregor parseModuleMapFile(ModMapFile); 4389194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 4399194a91dSDouglas Gregor } 4409194a91dSDouglas Gregor 4419194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 4429194a91dSDouglas Gregor inferred = InferredDirectories.insert( 4439194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 4449194a91dSDouglas Gregor } 4459194a91dSDouglas Gregor 4469194a91dSDouglas Gregor if (inferred->second.InferModules) { 4479194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 4489194a91dSDouglas Gregor // to infer this particular module. 4494ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 4509194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 4519194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 4529194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 4539194a91dSDouglas Gregor 4549194a91dSDouglas Gregor if (inferred->second.InferSystemModules) 4559194a91dSDouglas Gregor IsSystem = true; 4569194a91dSDouglas Gregor } 4579194a91dSDouglas Gregor } 4589194a91dSDouglas Gregor } 4599194a91dSDouglas Gregor 4609194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 4619194a91dSDouglas Gregor if (!canInfer) 4629194a91dSDouglas Gregor return 0; 4639194a91dSDouglas Gregor } 4649194a91dSDouglas Gregor 4659194a91dSDouglas Gregor 46656c64013SDouglas Gregor // Look for an umbrella header. 4672c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 46856c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 46956c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 470e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 47156c64013SDouglas Gregor 47256c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 47356c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 47456c64013SDouglas Gregor // idea. 47556c64013SDouglas Gregor if (!UmbrellaHeader) 47656c64013SDouglas Gregor return 0; 47756c64013SDouglas Gregor 478e89dbc1dSDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), Parent, 479e89dbc1dSDouglas Gregor /*IsFramework=*/true, /*IsExplicit=*/false); 480a686e1b0SDouglas Gregor if (IsSystem) 481a686e1b0SDouglas Gregor Result->IsSystem = IsSystem; 482a686e1b0SDouglas Gregor 483eb90e830SDouglas Gregor if (!Parent) 484e89dbc1dSDouglas Gregor Modules[ModuleName] = Result; 485e89dbc1dSDouglas Gregor 486322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 48773141fa9SDouglas Gregor Result->Umbrella = UmbrellaHeader; 48859527666SDouglas Gregor Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false); 4894dc71835SDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Result; 490d8bd7537SDouglas Gregor 491d8bd7537SDouglas Gregor // export * 492d8bd7537SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 493d8bd7537SDouglas Gregor 494a89c5ac4SDouglas Gregor // module * { export * } 495a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 496a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 497a89c5ac4SDouglas Gregor 498e89dbc1dSDouglas Gregor // Look for subframeworks. 499e89dbc1dSDouglas Gregor llvm::error_code EC; 5002c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 501ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 502e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 5032c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirNameNative; 504ddaa69cbSDouglas Gregor llvm::sys::path::native(SubframeworksDirName.str(), 505ddaa69cbSDouglas Gregor SubframeworksDirNameNative); 506ddaa69cbSDouglas Gregor for (llvm::sys::fs::directory_iterator 507ddaa69cbSDouglas Gregor Dir(SubframeworksDirNameNative.str(), EC), DirEnd; 508e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 509e89dbc1dSDouglas Gregor if (!StringRef(Dir->path()).endswith(".framework")) 510e89dbc1dSDouglas Gregor continue; 511f2161a70SDouglas Gregor 512e89dbc1dSDouglas Gregor if (const DirectoryEntry *SubframeworkDir 513e89dbc1dSDouglas Gregor = FileMgr.getDirectory(Dir->path())) { 51407c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 51507c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 51607c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 51707c22b78SDouglas Gregor // out to a top-level framework. 518e00c8b20SDouglas Gregor StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); 51907c22b78SDouglas Gregor bool FoundParent = false; 52007c22b78SDouglas Gregor do { 52107c22b78SDouglas Gregor // Get the parent directory name. 52207c22b78SDouglas Gregor SubframeworkDirName 52307c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 52407c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 52507c22b78SDouglas Gregor break; 52607c22b78SDouglas Gregor 52707c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 52807c22b78SDouglas Gregor FoundParent = true; 52907c22b78SDouglas Gregor break; 53007c22b78SDouglas Gregor } 53107c22b78SDouglas Gregor } while (true); 53207c22b78SDouglas Gregor 53307c22b78SDouglas Gregor if (!FoundParent) 53407c22b78SDouglas Gregor continue; 53507c22b78SDouglas Gregor 536e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 537056396aeSDouglas Gregor SmallString<32> NameBuf; 538056396aeSDouglas Gregor inferFrameworkModule(sanitizeFilenameAsIdentifier( 539056396aeSDouglas Gregor llvm::sys::path::stem(Dir->path()), NameBuf), 540056396aeSDouglas Gregor SubframeworkDir, IsSystem, Result); 541e89dbc1dSDouglas Gregor } 542e89dbc1dSDouglas Gregor } 543e89dbc1dSDouglas Gregor 54411dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 54511dfe6feSDouglas Gregor // framework. 54611dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 54711dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 54811dfe6feSDouglas Gregor } 54911dfe6feSDouglas Gregor 55056c64013SDouglas Gregor return Result; 55156c64013SDouglas Gregor } 55256c64013SDouglas Gregor 553a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ 55459527666SDouglas Gregor Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false); 55573141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 5567033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 557a89c5ac4SDouglas Gregor } 558a89c5ac4SDouglas Gregor 559524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) { 560524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 561524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 562524e33e1SDouglas Gregor } 563524e33e1SDouglas Gregor 56459527666SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header, 56559527666SDouglas Gregor bool Excluded) { 566b146baabSArgyrios Kyrtzidis if (Excluded) { 56759527666SDouglas Gregor Mod->ExcludedHeaders.push_back(Header); 568b146baabSArgyrios Kyrtzidis } else { 569a89c5ac4SDouglas Gregor Mod->Headers.push_back(Header); 570b146baabSArgyrios Kyrtzidis HeaderInfo.MarkFileModuleHeader(Header); 571b146baabSArgyrios Kyrtzidis } 57259527666SDouglas Gregor Headers[Header] = KnownHeader(Mod, Excluded); 573a89c5ac4SDouglas Gregor } 574a89c5ac4SDouglas Gregor 575514b636aSDouglas Gregor const FileEntry * 576e4412640SArgyrios Kyrtzidis ModuleMap::getContainingModuleMapFile(Module *Module) const { 577514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 578514b636aSDouglas Gregor return 0; 579514b636aSDouglas Gregor 580514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 581514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 582514b636aSDouglas Gregor } 583514b636aSDouglas Gregor 584718292f2SDouglas Gregor void ModuleMap::dump() { 585718292f2SDouglas Gregor llvm::errs() << "Modules:"; 586718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 587718292f2SDouglas Gregor MEnd = Modules.end(); 588718292f2SDouglas Gregor M != MEnd; ++M) 589d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 590718292f2SDouglas Gregor 591718292f2SDouglas Gregor llvm::errs() << "Headers:"; 59259527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 593718292f2SDouglas Gregor H != HEnd; ++H) { 594718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 59559527666SDouglas Gregor << H->second.getModule()->getFullModuleName() << "\n"; 596718292f2SDouglas Gregor } 597718292f2SDouglas Gregor } 598718292f2SDouglas Gregor 5992b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 6002b82c2a5SDouglas Gregor bool HadError = false; 6012b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 6022b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 6032b82c2a5SDouglas Gregor Complain); 604f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 6052b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 6062b82c2a5SDouglas Gregor else 6072b82c2a5SDouglas Gregor HadError = true; 6082b82c2a5SDouglas Gregor } 6092b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 6102b82c2a5SDouglas Gregor return HadError; 6112b82c2a5SDouglas Gregor } 6122b82c2a5SDouglas Gregor 613*fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 614*fb912657SDouglas Gregor bool HadError = false; 615*fb912657SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedConflicts.size(); I != N; ++I) { 616*fb912657SDouglas Gregor Module *OtherMod = resolveModuleId(Mod->UnresolvedConflicts[I].Id, 617*fb912657SDouglas Gregor Mod, Complain); 618*fb912657SDouglas Gregor if (!OtherMod) { 619*fb912657SDouglas Gregor HadError = true; 620*fb912657SDouglas Gregor continue; 621*fb912657SDouglas Gregor } 622*fb912657SDouglas Gregor 623*fb912657SDouglas Gregor Module::Conflict Conflict; 624*fb912657SDouglas Gregor Conflict.Other = OtherMod; 625*fb912657SDouglas Gregor Conflict.Message = Mod->UnresolvedConflicts[I].Message; 626*fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 627*fb912657SDouglas Gregor } 628*fb912657SDouglas Gregor Mod->UnresolvedConflicts.clear(); 629*fb912657SDouglas Gregor return HadError; 630*fb912657SDouglas Gregor } 631*fb912657SDouglas Gregor 6320093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { 6330093b3c7SDouglas Gregor if (Loc.isInvalid()) 6340093b3c7SDouglas Gregor return 0; 6350093b3c7SDouglas Gregor 6360093b3c7SDouglas Gregor // Use the expansion location to determine which module we're in. 6370093b3c7SDouglas Gregor FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); 6380093b3c7SDouglas Gregor if (!ExpansionLoc.isFileID()) 6390093b3c7SDouglas Gregor return 0; 6400093b3c7SDouglas Gregor 6410093b3c7SDouglas Gregor 6420093b3c7SDouglas Gregor const SourceManager &SrcMgr = Loc.getManager(); 6430093b3c7SDouglas Gregor FileID ExpansionFileID = ExpansionLoc.getFileID(); 644224d8a74SDouglas Gregor 645224d8a74SDouglas Gregor while (const FileEntry *ExpansionFile 646224d8a74SDouglas Gregor = SrcMgr.getFileEntryForID(ExpansionFileID)) { 647224d8a74SDouglas Gregor // Find the module that owns this header (if any). 648224d8a74SDouglas Gregor if (Module *Mod = findModuleForHeader(ExpansionFile)) 649224d8a74SDouglas Gregor return Mod; 650224d8a74SDouglas Gregor 651224d8a74SDouglas Gregor // No module owns this header, so look up the inclusion chain to see if 652224d8a74SDouglas Gregor // any included header has an associated module. 653224d8a74SDouglas Gregor SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID); 654224d8a74SDouglas Gregor if (IncludeLoc.isInvalid()) 6550093b3c7SDouglas Gregor return 0; 6560093b3c7SDouglas Gregor 657224d8a74SDouglas Gregor ExpansionFileID = SrcMgr.getFileID(IncludeLoc); 658224d8a74SDouglas Gregor } 659224d8a74SDouglas Gregor 660224d8a74SDouglas Gregor return 0; 6610093b3c7SDouglas Gregor } 6620093b3c7SDouglas Gregor 663718292f2SDouglas Gregor //----------------------------------------------------------------------------// 664718292f2SDouglas Gregor // Module map file parser 665718292f2SDouglas Gregor //----------------------------------------------------------------------------// 666718292f2SDouglas Gregor 667718292f2SDouglas Gregor namespace clang { 668718292f2SDouglas Gregor /// \brief A token in a module map file. 669718292f2SDouglas Gregor struct MMToken { 670718292f2SDouglas Gregor enum TokenKind { 6711fb5c3a6SDouglas Gregor Comma, 67235b13eceSDouglas Gregor ConfigMacros, 673*fb912657SDouglas Gregor Conflict, 674718292f2SDouglas Gregor EndOfFile, 675718292f2SDouglas Gregor HeaderKeyword, 676718292f2SDouglas Gregor Identifier, 67759527666SDouglas Gregor ExcludeKeyword, 678718292f2SDouglas Gregor ExplicitKeyword, 6792b82c2a5SDouglas Gregor ExportKeyword, 680755b2055SDouglas Gregor FrameworkKeyword, 6816ddfca91SDouglas Gregor LinkKeyword, 682718292f2SDouglas Gregor ModuleKeyword, 6832b82c2a5SDouglas Gregor Period, 684718292f2SDouglas Gregor UmbrellaKeyword, 6851fb5c3a6SDouglas Gregor RequiresKeyword, 6862b82c2a5SDouglas Gregor Star, 687718292f2SDouglas Gregor StringLiteral, 688718292f2SDouglas Gregor LBrace, 689a686e1b0SDouglas Gregor RBrace, 690a686e1b0SDouglas Gregor LSquare, 691a686e1b0SDouglas Gregor RSquare 692718292f2SDouglas Gregor } Kind; 693718292f2SDouglas Gregor 694718292f2SDouglas Gregor unsigned Location; 695718292f2SDouglas Gregor unsigned StringLength; 696718292f2SDouglas Gregor const char *StringData; 697718292f2SDouglas Gregor 698718292f2SDouglas Gregor void clear() { 699718292f2SDouglas Gregor Kind = EndOfFile; 700718292f2SDouglas Gregor Location = 0; 701718292f2SDouglas Gregor StringLength = 0; 702718292f2SDouglas Gregor StringData = 0; 703718292f2SDouglas Gregor } 704718292f2SDouglas Gregor 705718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 706718292f2SDouglas Gregor 707718292f2SDouglas Gregor SourceLocation getLocation() const { 708718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 709718292f2SDouglas Gregor } 710718292f2SDouglas Gregor 711718292f2SDouglas Gregor StringRef getString() const { 712718292f2SDouglas Gregor return StringRef(StringData, StringLength); 713718292f2SDouglas Gregor } 714718292f2SDouglas Gregor }; 715718292f2SDouglas Gregor 7169194a91dSDouglas Gregor /// \brief The set of attributes that can be attached to a module. 7174442605fSBill Wendling struct Attributes { 71835b13eceSDouglas Gregor Attributes() : IsSystem(), IsExhaustive() { } 7199194a91dSDouglas Gregor 7209194a91dSDouglas Gregor /// \brief Whether this is a system module. 7219194a91dSDouglas Gregor unsigned IsSystem : 1; 72235b13eceSDouglas Gregor 72335b13eceSDouglas Gregor /// \brief Whether this is an exhaustive set of configuration macros. 72435b13eceSDouglas Gregor unsigned IsExhaustive : 1; 7259194a91dSDouglas Gregor }; 7269194a91dSDouglas Gregor 7279194a91dSDouglas Gregor 728718292f2SDouglas Gregor class ModuleMapParser { 729718292f2SDouglas Gregor Lexer &L; 730718292f2SDouglas Gregor SourceManager &SourceMgr; 731bc10b9fbSDouglas Gregor 732bc10b9fbSDouglas Gregor /// \brief Default target information, used only for string literal 733bc10b9fbSDouglas Gregor /// parsing. 734bc10b9fbSDouglas Gregor const TargetInfo *Target; 735bc10b9fbSDouglas Gregor 736718292f2SDouglas Gregor DiagnosticsEngine &Diags; 737718292f2SDouglas Gregor ModuleMap ⤅ 738718292f2SDouglas Gregor 7395257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 7405257fc63SDouglas Gregor const DirectoryEntry *Directory; 7415257fc63SDouglas Gregor 7423ec6663bSDouglas Gregor /// \brief The directory containing Clang-supplied headers. 7433ec6663bSDouglas Gregor const DirectoryEntry *BuiltinIncludeDir; 7443ec6663bSDouglas Gregor 745718292f2SDouglas Gregor /// \brief Whether an error occurred. 746718292f2SDouglas Gregor bool HadError; 747718292f2SDouglas Gregor 748718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 749718292f2SDouglas Gregor /// during parsing. 750718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 751718292f2SDouglas Gregor 752718292f2SDouglas Gregor /// \brief The current token. 753718292f2SDouglas Gregor MMToken Tok; 754718292f2SDouglas Gregor 755718292f2SDouglas Gregor /// \brief The active module. 756de3ef502SDouglas Gregor Module *ActiveModule; 757718292f2SDouglas Gregor 758718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 759718292f2SDouglas Gregor SourceLocation consumeToken(); 760718292f2SDouglas Gregor 761718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 762718292f2SDouglas Gregor /// (or the end of the file). 763718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 764718292f2SDouglas Gregor 765f857950dSDmitri Gribenko typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId; 766e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 767718292f2SDouglas Gregor void parseModuleDecl(); 7681fb5c3a6SDouglas Gregor void parseRequiresDecl(); 76959527666SDouglas Gregor void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc); 770524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 7712b82c2a5SDouglas Gregor void parseExportDecl(); 7726ddfca91SDouglas Gregor void parseLinkDecl(); 77335b13eceSDouglas Gregor void parseConfigMacros(); 774*fb912657SDouglas Gregor void parseConflict(); 7759194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 7764442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 777718292f2SDouglas Gregor 7787033127bSDouglas Gregor const DirectoryEntry *getOverriddenHeaderSearchDir(); 7797033127bSDouglas Gregor 780718292f2SDouglas Gregor public: 781718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 782bc10b9fbSDouglas Gregor const TargetInfo *Target, 783718292f2SDouglas Gregor DiagnosticsEngine &Diags, 7845257fc63SDouglas Gregor ModuleMap &Map, 7853ec6663bSDouglas Gregor const DirectoryEntry *Directory, 7863ec6663bSDouglas Gregor const DirectoryEntry *BuiltinIncludeDir) 787bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 7883ec6663bSDouglas Gregor Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir), 7893ec6663bSDouglas Gregor HadError(false), ActiveModule(0) 790718292f2SDouglas Gregor { 791718292f2SDouglas Gregor Tok.clear(); 792718292f2SDouglas Gregor consumeToken(); 793718292f2SDouglas Gregor } 794718292f2SDouglas Gregor 795718292f2SDouglas Gregor bool parseModuleMapFile(); 796718292f2SDouglas Gregor }; 797718292f2SDouglas Gregor } 798718292f2SDouglas Gregor 799718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 800718292f2SDouglas Gregor retry: 801718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 802718292f2SDouglas Gregor Tok.clear(); 803718292f2SDouglas Gregor 804718292f2SDouglas Gregor Token LToken; 805718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 806718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 807718292f2SDouglas Gregor switch (LToken.getKind()) { 808718292f2SDouglas Gregor case tok::raw_identifier: 809718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 810718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 811718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 81235b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 813*fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 81459527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 815718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 8162b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 817755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 81835b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 8196ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 820718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 8211fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 822718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 823718292f2SDouglas Gregor .Default(MMToken::Identifier); 824718292f2SDouglas Gregor break; 825718292f2SDouglas Gregor 8261fb5c3a6SDouglas Gregor case tok::comma: 8271fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 8281fb5c3a6SDouglas Gregor break; 8291fb5c3a6SDouglas Gregor 830718292f2SDouglas Gregor case tok::eof: 831718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 832718292f2SDouglas Gregor break; 833718292f2SDouglas Gregor 834718292f2SDouglas Gregor case tok::l_brace: 835718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 836718292f2SDouglas Gregor break; 837718292f2SDouglas Gregor 838a686e1b0SDouglas Gregor case tok::l_square: 839a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 840a686e1b0SDouglas Gregor break; 841a686e1b0SDouglas Gregor 8422b82c2a5SDouglas Gregor case tok::period: 8432b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 8442b82c2a5SDouglas Gregor break; 8452b82c2a5SDouglas Gregor 846718292f2SDouglas Gregor case tok::r_brace: 847718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 848718292f2SDouglas Gregor break; 849718292f2SDouglas Gregor 850a686e1b0SDouglas Gregor case tok::r_square: 851a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 852a686e1b0SDouglas Gregor break; 853a686e1b0SDouglas Gregor 8542b82c2a5SDouglas Gregor case tok::star: 8552b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 8562b82c2a5SDouglas Gregor break; 8572b82c2a5SDouglas Gregor 858718292f2SDouglas Gregor case tok::string_literal: { 859d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 860d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 861d67aea28SRichard Smith HadError = true; 862d67aea28SRichard Smith goto retry; 863d67aea28SRichard Smith } 864d67aea28SRichard Smith 865718292f2SDouglas Gregor // Parse the string literal. 866718292f2SDouglas Gregor LangOptions LangOpts; 867718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 868718292f2SDouglas Gregor if (StringLiteral.hadError) 869718292f2SDouglas Gregor goto retry; 870718292f2SDouglas Gregor 871718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 872718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 873718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 874718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 875718292f2SDouglas Gregor Saved[Length] = 0; 876718292f2SDouglas Gregor 877718292f2SDouglas Gregor // Form the token. 878718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 879718292f2SDouglas Gregor Tok.StringData = Saved; 880718292f2SDouglas Gregor Tok.StringLength = Length; 881718292f2SDouglas Gregor break; 882718292f2SDouglas Gregor } 883718292f2SDouglas Gregor 884718292f2SDouglas Gregor case tok::comment: 885718292f2SDouglas Gregor goto retry; 886718292f2SDouglas Gregor 887718292f2SDouglas Gregor default: 888718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 889718292f2SDouglas Gregor HadError = true; 890718292f2SDouglas Gregor goto retry; 891718292f2SDouglas Gregor } 892718292f2SDouglas Gregor 893718292f2SDouglas Gregor return Result; 894718292f2SDouglas Gregor } 895718292f2SDouglas Gregor 896718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 897718292f2SDouglas Gregor unsigned braceDepth = 0; 898a686e1b0SDouglas Gregor unsigned squareDepth = 0; 899718292f2SDouglas Gregor do { 900718292f2SDouglas Gregor switch (Tok.Kind) { 901718292f2SDouglas Gregor case MMToken::EndOfFile: 902718292f2SDouglas Gregor return; 903718292f2SDouglas Gregor 904718292f2SDouglas Gregor case MMToken::LBrace: 905a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 906718292f2SDouglas Gregor return; 907718292f2SDouglas Gregor 908718292f2SDouglas Gregor ++braceDepth; 909718292f2SDouglas Gregor break; 910718292f2SDouglas Gregor 911a686e1b0SDouglas Gregor case MMToken::LSquare: 912a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 913a686e1b0SDouglas Gregor return; 914a686e1b0SDouglas Gregor 915a686e1b0SDouglas Gregor ++squareDepth; 916a686e1b0SDouglas Gregor break; 917a686e1b0SDouglas Gregor 918718292f2SDouglas Gregor case MMToken::RBrace: 919718292f2SDouglas Gregor if (braceDepth > 0) 920718292f2SDouglas Gregor --braceDepth; 921718292f2SDouglas Gregor else if (Tok.is(K)) 922718292f2SDouglas Gregor return; 923718292f2SDouglas Gregor break; 924718292f2SDouglas Gregor 925a686e1b0SDouglas Gregor case MMToken::RSquare: 926a686e1b0SDouglas Gregor if (squareDepth > 0) 927a686e1b0SDouglas Gregor --squareDepth; 928a686e1b0SDouglas Gregor else if (Tok.is(K)) 929a686e1b0SDouglas Gregor return; 930a686e1b0SDouglas Gregor break; 931a686e1b0SDouglas Gregor 932718292f2SDouglas Gregor default: 933a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 934718292f2SDouglas Gregor return; 935718292f2SDouglas Gregor break; 936718292f2SDouglas Gregor } 937718292f2SDouglas Gregor 938718292f2SDouglas Gregor consumeToken(); 939718292f2SDouglas Gregor } while (true); 940718292f2SDouglas Gregor } 941718292f2SDouglas Gregor 942e7ab3669SDouglas Gregor /// \brief Parse a module-id. 943e7ab3669SDouglas Gregor /// 944e7ab3669SDouglas Gregor /// module-id: 945e7ab3669SDouglas Gregor /// identifier 946e7ab3669SDouglas Gregor /// identifier '.' module-id 947e7ab3669SDouglas Gregor /// 948e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 949e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 950e7ab3669SDouglas Gregor Id.clear(); 951e7ab3669SDouglas Gregor do { 952e7ab3669SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 953e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 954e7ab3669SDouglas Gregor consumeToken(); 955e7ab3669SDouglas Gregor } else { 956e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 957e7ab3669SDouglas Gregor return true; 958e7ab3669SDouglas Gregor } 959e7ab3669SDouglas Gregor 960e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 961e7ab3669SDouglas Gregor break; 962e7ab3669SDouglas Gregor 963e7ab3669SDouglas Gregor consumeToken(); 964e7ab3669SDouglas Gregor } while (true); 965e7ab3669SDouglas Gregor 966e7ab3669SDouglas Gregor return false; 967e7ab3669SDouglas Gregor } 968e7ab3669SDouglas Gregor 969a686e1b0SDouglas Gregor namespace { 970a686e1b0SDouglas Gregor /// \brief Enumerates the known attributes. 971a686e1b0SDouglas Gregor enum AttributeKind { 972a686e1b0SDouglas Gregor /// \brief An unknown attribute. 973a686e1b0SDouglas Gregor AT_unknown, 974a686e1b0SDouglas Gregor /// \brief The 'system' attribute. 97535b13eceSDouglas Gregor AT_system, 97635b13eceSDouglas Gregor /// \brief The 'exhaustive' attribute. 97735b13eceSDouglas Gregor AT_exhaustive 978a686e1b0SDouglas Gregor }; 979a686e1b0SDouglas Gregor } 980a686e1b0SDouglas Gregor 981718292f2SDouglas Gregor /// \brief Parse a module declaration. 982718292f2SDouglas Gregor /// 983718292f2SDouglas Gregor /// module-declaration: 984a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 985a686e1b0SDouglas Gregor /// { module-member* } 986a686e1b0SDouglas Gregor /// 987718292f2SDouglas Gregor /// module-member: 9881fb5c3a6SDouglas Gregor /// requires-declaration 989718292f2SDouglas Gregor /// header-declaration 990e7ab3669SDouglas Gregor /// submodule-declaration 9912b82c2a5SDouglas Gregor /// export-declaration 9926ddfca91SDouglas Gregor /// link-declaration 99373441091SDouglas Gregor /// 99473441091SDouglas Gregor /// submodule-declaration: 99573441091SDouglas Gregor /// module-declaration 99673441091SDouglas Gregor /// inferred-submodule-declaration 997718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 998755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 999755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 1000f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1001e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 1002718292f2SDouglas Gregor bool Explicit = false; 1003f2161a70SDouglas Gregor bool Framework = false; 1004755b2055SDouglas Gregor 1005f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1006f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1007e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1008f2161a70SDouglas Gregor Explicit = true; 1009f2161a70SDouglas Gregor } 1010f2161a70SDouglas Gregor 1011f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1012755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 1013755b2055SDouglas Gregor consumeToken(); 1014755b2055SDouglas Gregor Framework = true; 1015755b2055SDouglas Gregor } 1016718292f2SDouglas Gregor 1017718292f2SDouglas Gregor // Parse 'module' keyword. 1018718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1019d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1020718292f2SDouglas Gregor consumeToken(); 1021718292f2SDouglas Gregor HadError = true; 1022718292f2SDouglas Gregor return; 1023718292f2SDouglas Gregor } 1024718292f2SDouglas Gregor consumeToken(); // 'module' keyword 1025718292f2SDouglas Gregor 102673441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 102773441091SDouglas Gregor // Parse it. 102873441091SDouglas Gregor if (Tok.is(MMToken::Star)) 10299194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 103073441091SDouglas Gregor 1031718292f2SDouglas Gregor // Parse the module name. 1032e7ab3669SDouglas Gregor ModuleId Id; 1033e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1034718292f2SDouglas Gregor HadError = true; 1035718292f2SDouglas Gregor return; 1036718292f2SDouglas Gregor } 1037e7ab3669SDouglas Gregor 1038e7ab3669SDouglas Gregor if (ActiveModule) { 1039e7ab3669SDouglas Gregor if (Id.size() > 1) { 1040e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1041e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1042e7ab3669SDouglas Gregor 1043e7ab3669SDouglas Gregor HadError = true; 1044e7ab3669SDouglas Gregor return; 1045e7ab3669SDouglas Gregor } 1046e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1047e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1048e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1049e7ab3669SDouglas Gregor Explicit = false; 1050e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1051e7ab3669SDouglas Gregor HadError = true; 1052e7ab3669SDouglas Gregor } 1053e7ab3669SDouglas Gregor 1054e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1055e7ab3669SDouglas Gregor if (Id.size() > 1) { 1056e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1057e7ab3669SDouglas Gregor // is a submodule. 1058e7ab3669SDouglas Gregor ActiveModule = 0; 1059e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1060e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 1061e7ab3669SDouglas Gregor ActiveModule = Next; 1062e7ab3669SDouglas Gregor continue; 1063e7ab3669SDouglas Gregor } 1064e7ab3669SDouglas Gregor 1065e7ab3669SDouglas Gregor if (ActiveModule) { 1066e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 1067e7ab3669SDouglas Gregor << Id[I].first << ActiveModule->getTopLevelModule(); 1068e7ab3669SDouglas Gregor } else { 1069e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1070e7ab3669SDouglas Gregor } 1071e7ab3669SDouglas Gregor HadError = true; 1072e7ab3669SDouglas Gregor return; 1073e7ab3669SDouglas Gregor } 1074e7ab3669SDouglas Gregor } 1075e7ab3669SDouglas Gregor 1076e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1077e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1078718292f2SDouglas Gregor 1079a686e1b0SDouglas Gregor // Parse the optional attribute list. 10804442605fSBill Wendling Attributes Attrs; 10819194a91dSDouglas Gregor parseOptionalAttributes(Attrs); 1082a686e1b0SDouglas Gregor 1083718292f2SDouglas Gregor // Parse the opening brace. 1084718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1085718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1086718292f2SDouglas Gregor << ModuleName; 1087718292f2SDouglas Gregor HadError = true; 1088718292f2SDouglas Gregor return; 1089718292f2SDouglas Gregor } 1090718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1091718292f2SDouglas Gregor 1092718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 1093eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 1094fcc54a3bSDouglas Gregor if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) { 1095fcc54a3bSDouglas Gregor // Skip the module definition. 1096fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1097fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1098fcc54a3bSDouglas Gregor consumeToken(); 1099fcc54a3bSDouglas Gregor else { 1100fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1101fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1102fcc54a3bSDouglas Gregor HadError = true; 1103fcc54a3bSDouglas Gregor } 1104fcc54a3bSDouglas Gregor return; 1105fcc54a3bSDouglas Gregor } 1106fcc54a3bSDouglas Gregor 1107718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1108718292f2SDouglas Gregor << ModuleName; 1109eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1110718292f2SDouglas Gregor 1111718292f2SDouglas Gregor // Skip the module definition. 1112718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1113718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1114718292f2SDouglas Gregor consumeToken(); 1115718292f2SDouglas Gregor 1116718292f2SDouglas Gregor HadError = true; 1117718292f2SDouglas Gregor return; 1118718292f2SDouglas Gregor } 1119718292f2SDouglas Gregor 1120718292f2SDouglas Gregor // Start defining this module. 1121eb90e830SDouglas Gregor ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, 1122eb90e830SDouglas Gregor Explicit).first; 1123eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 11249194a91dSDouglas Gregor if (Attrs.IsSystem) 1125a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 1126718292f2SDouglas Gregor 1127718292f2SDouglas Gregor bool Done = false; 1128718292f2SDouglas Gregor do { 1129718292f2SDouglas Gregor switch (Tok.Kind) { 1130718292f2SDouglas Gregor case MMToken::EndOfFile: 1131718292f2SDouglas Gregor case MMToken::RBrace: 1132718292f2SDouglas Gregor Done = true; 1133718292f2SDouglas Gregor break; 1134718292f2SDouglas Gregor 113535b13eceSDouglas Gregor case MMToken::ConfigMacros: 113635b13eceSDouglas Gregor parseConfigMacros(); 113735b13eceSDouglas Gregor break; 113835b13eceSDouglas Gregor 1139*fb912657SDouglas Gregor case MMToken::Conflict: 1140*fb912657SDouglas Gregor parseConflict(); 1141*fb912657SDouglas Gregor break; 1142*fb912657SDouglas Gregor 1143718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 1144f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1145718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1146718292f2SDouglas Gregor parseModuleDecl(); 1147718292f2SDouglas Gregor break; 1148718292f2SDouglas Gregor 11492b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 11502b82c2a5SDouglas Gregor parseExportDecl(); 11512b82c2a5SDouglas Gregor break; 11522b82c2a5SDouglas Gregor 11531fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 11541fb5c3a6SDouglas Gregor parseRequiresDecl(); 11551fb5c3a6SDouglas Gregor break; 11561fb5c3a6SDouglas Gregor 1157524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 1158524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 1159524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 116059527666SDouglas Gregor parseHeaderDecl(UmbrellaLoc, SourceLocation()); 1161524e33e1SDouglas Gregor else 1162524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 1163718292f2SDouglas Gregor break; 1164524e33e1SDouglas Gregor } 1165718292f2SDouglas Gregor 116659527666SDouglas Gregor case MMToken::ExcludeKeyword: { 116759527666SDouglas Gregor SourceLocation ExcludeLoc = consumeToken(); 116859527666SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) { 116959527666SDouglas Gregor parseHeaderDecl(SourceLocation(), ExcludeLoc); 117059527666SDouglas Gregor } else { 117159527666SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 117259527666SDouglas Gregor << "exclude"; 117359527666SDouglas Gregor } 117459527666SDouglas Gregor break; 117559527666SDouglas Gregor } 117659527666SDouglas Gregor 1177322f633cSDouglas Gregor case MMToken::HeaderKeyword: 117859527666SDouglas Gregor parseHeaderDecl(SourceLocation(), SourceLocation()); 1179718292f2SDouglas Gregor break; 1180718292f2SDouglas Gregor 11816ddfca91SDouglas Gregor case MMToken::LinkKeyword: 11826ddfca91SDouglas Gregor parseLinkDecl(); 11836ddfca91SDouglas Gregor break; 11846ddfca91SDouglas Gregor 1185718292f2SDouglas Gregor default: 1186718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 1187718292f2SDouglas Gregor consumeToken(); 1188718292f2SDouglas Gregor break; 1189718292f2SDouglas Gregor } 1190718292f2SDouglas Gregor } while (!Done); 1191718292f2SDouglas Gregor 1192718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1193718292f2SDouglas Gregor consumeToken(); 1194718292f2SDouglas Gregor else { 1195718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1196718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1197718292f2SDouglas Gregor HadError = true; 1198718292f2SDouglas Gregor } 1199718292f2SDouglas Gregor 120011dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 120111dfe6feSDouglas Gregor // libraries, automatically link against the framework. 120211dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 120311dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 120411dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 120511dfe6feSDouglas Gregor } 120611dfe6feSDouglas Gregor 1207e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 1208e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 1209718292f2SDouglas Gregor } 1210718292f2SDouglas Gregor 12111fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration. 12121fb5c3a6SDouglas Gregor /// 12131fb5c3a6SDouglas Gregor /// requires-declaration: 12141fb5c3a6SDouglas Gregor /// 'requires' feature-list 12151fb5c3a6SDouglas Gregor /// 12161fb5c3a6SDouglas Gregor /// feature-list: 12171fb5c3a6SDouglas Gregor /// identifier ',' feature-list 12181fb5c3a6SDouglas Gregor /// identifier 12191fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 12201fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 12211fb5c3a6SDouglas Gregor 12221fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 12231fb5c3a6SDouglas Gregor consumeToken(); 12241fb5c3a6SDouglas Gregor 12251fb5c3a6SDouglas Gregor // Parse the feature-list. 12261fb5c3a6SDouglas Gregor do { 12271fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 12281fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 12291fb5c3a6SDouglas Gregor HadError = true; 12301fb5c3a6SDouglas Gregor return; 12311fb5c3a6SDouglas Gregor } 12321fb5c3a6SDouglas Gregor 12331fb5c3a6SDouglas Gregor // Consume the feature name. 12341fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 12351fb5c3a6SDouglas Gregor consumeToken(); 12361fb5c3a6SDouglas Gregor 12371fb5c3a6SDouglas Gregor // Add this feature. 123889929282SDouglas Gregor ActiveModule->addRequirement(Feature, Map.LangOpts, *Map.Target); 12391fb5c3a6SDouglas Gregor 12401fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 12411fb5c3a6SDouglas Gregor break; 12421fb5c3a6SDouglas Gregor 12431fb5c3a6SDouglas Gregor // Consume the comma. 12441fb5c3a6SDouglas Gregor consumeToken(); 12451fb5c3a6SDouglas Gregor } while (true); 12461fb5c3a6SDouglas Gregor } 12471fb5c3a6SDouglas Gregor 1248f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the 1249f2161a70SDouglas Gregor /// subframework in which the given module lives. 1250bf8da9d7SBenjamin Kramer static void appendSubframeworkPaths(Module *Mod, 1251f857950dSDmitri Gribenko SmallVectorImpl<char> &Path) { 1252f2161a70SDouglas Gregor // Collect the framework names from the given module to the top-level module. 1253f857950dSDmitri Gribenko SmallVector<StringRef, 2> Paths; 1254f2161a70SDouglas Gregor for (; Mod; Mod = Mod->Parent) { 1255f2161a70SDouglas Gregor if (Mod->IsFramework) 1256f2161a70SDouglas Gregor Paths.push_back(Mod->Name); 1257f2161a70SDouglas Gregor } 1258f2161a70SDouglas Gregor 1259f2161a70SDouglas Gregor if (Paths.empty()) 1260f2161a70SDouglas Gregor return; 1261f2161a70SDouglas Gregor 1262f2161a70SDouglas Gregor // Add Frameworks/Name.framework for each subframework. 1263f2161a70SDouglas Gregor for (unsigned I = Paths.size() - 1; I != 0; --I) { 1264f2161a70SDouglas Gregor llvm::sys::path::append(Path, "Frameworks"); 1265f2161a70SDouglas Gregor llvm::sys::path::append(Path, Paths[I-1] + ".framework"); 1266f2161a70SDouglas Gregor } 1267f2161a70SDouglas Gregor } 1268f2161a70SDouglas Gregor 12693ec6663bSDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin 12703ec6663bSDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 12713ec6663bSDouglas Gregor /// headers. 12723ec6663bSDouglas Gregor static bool isBuiltinHeader(StringRef FileName) { 12733ec6663bSDouglas Gregor return llvm::StringSwitch<bool>(FileName) 12743ec6663bSDouglas Gregor .Case("float.h", true) 12753ec6663bSDouglas Gregor .Case("iso646.h", true) 12763ec6663bSDouglas Gregor .Case("limits.h", true) 12773ec6663bSDouglas Gregor .Case("stdalign.h", true) 12783ec6663bSDouglas Gregor .Case("stdarg.h", true) 12793ec6663bSDouglas Gregor .Case("stdbool.h", true) 12803ec6663bSDouglas Gregor .Case("stddef.h", true) 12813ec6663bSDouglas Gregor .Case("stdint.h", true) 12823ec6663bSDouglas Gregor .Case("tgmath.h", true) 12833ec6663bSDouglas Gregor .Case("unwind.h", true) 12843ec6663bSDouglas Gregor .Default(false); 12853ec6663bSDouglas Gregor } 12863ec6663bSDouglas Gregor 1287718292f2SDouglas Gregor /// \brief Parse a header declaration. 1288718292f2SDouglas Gregor /// 1289718292f2SDouglas Gregor /// header-declaration: 1290322f633cSDouglas Gregor /// 'umbrella'[opt] 'header' string-literal 129159527666SDouglas Gregor /// 'exclude'[opt] 'header' string-literal 129259527666SDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc, 129359527666SDouglas Gregor SourceLocation ExcludeLoc) { 1294718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 12951871ed3dSBenjamin Kramer consumeToken(); 1296718292f2SDouglas Gregor 1297322f633cSDouglas Gregor bool Umbrella = UmbrellaLoc.isValid(); 129859527666SDouglas Gregor bool Exclude = ExcludeLoc.isValid(); 129959527666SDouglas Gregor assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'"); 1300718292f2SDouglas Gregor // Parse the header name. 1301718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1302718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 1303718292f2SDouglas Gregor << "header"; 1304718292f2SDouglas Gregor HadError = true; 1305718292f2SDouglas Gregor return; 1306718292f2SDouglas Gregor } 1307e7ab3669SDouglas Gregor std::string FileName = Tok.getString(); 1308718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 1309718292f2SDouglas Gregor 1310524e33e1SDouglas Gregor // Check whether we already have an umbrella. 1311524e33e1SDouglas Gregor if (Umbrella && ActiveModule->Umbrella) { 1312524e33e1SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash) 1313524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 1314322f633cSDouglas Gregor HadError = true; 1315322f633cSDouglas Gregor return; 1316322f633cSDouglas Gregor } 1317322f633cSDouglas Gregor 13185257fc63SDouglas Gregor // Look for this file. 1319e7ab3669SDouglas Gregor const FileEntry *File = 0; 13203ec6663bSDouglas Gregor const FileEntry *BuiltinFile = 0; 13212c1dd271SDylan Noblesmith SmallString<128> PathName; 1322e7ab3669SDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 1323e7ab3669SDouglas Gregor PathName = FileName; 1324e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 13257033127bSDouglas Gregor } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) { 13267033127bSDouglas Gregor PathName = Dir->getName(); 13277033127bSDouglas Gregor llvm::sys::path::append(PathName, FileName); 13287033127bSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1329e7ab3669SDouglas Gregor } else { 1330e7ab3669SDouglas Gregor // Search for the header file within the search directory. 13317033127bSDouglas Gregor PathName = Directory->getName(); 1332e7ab3669SDouglas Gregor unsigned PathLength = PathName.size(); 1333755b2055SDouglas Gregor 1334f2161a70SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 1335f2161a70SDouglas Gregor appendSubframeworkPaths(ActiveModule, PathName); 1336755b2055SDouglas Gregor 1337e7ab3669SDouglas Gregor // Check whether this file is in the public headers. 1338e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 13395257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1340e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1341e7ab3669SDouglas Gregor 1342e7ab3669SDouglas Gregor if (!File) { 1343e7ab3669SDouglas Gregor // Check whether this file is in the private headers. 1344e7ab3669SDouglas Gregor PathName.resize(PathLength); 1345e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 1346e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1347e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1348e7ab3669SDouglas Gregor } 1349e7ab3669SDouglas Gregor } else { 1350e7ab3669SDouglas Gregor // Lookup for normal headers. 1351e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1352e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 13533ec6663bSDouglas Gregor 13543ec6663bSDouglas Gregor // If this is a system module with a top-level header, this header 13553ec6663bSDouglas Gregor // may have a counterpart (or replacement) in the set of headers 13563ec6663bSDouglas Gregor // supplied by Clang. Find that builtin header. 13573ec6663bSDouglas Gregor if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir && 13583ec6663bSDouglas Gregor BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) { 13592c1dd271SDylan Noblesmith SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); 13603ec6663bSDouglas Gregor llvm::sys::path::append(BuiltinPathName, FileName); 13613ec6663bSDouglas Gregor BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); 13623ec6663bSDouglas Gregor 13633ec6663bSDouglas Gregor // If Clang supplies this header but the underlying system does not, 13643ec6663bSDouglas Gregor // just silently swap in our builtin version. Otherwise, we'll end 13653ec6663bSDouglas Gregor // up adding both (later). 13663ec6663bSDouglas Gregor if (!File && BuiltinFile) { 13673ec6663bSDouglas Gregor File = BuiltinFile; 13683ec6663bSDouglas Gregor BuiltinFile = 0; 13693ec6663bSDouglas Gregor } 13703ec6663bSDouglas Gregor } 1371e7ab3669SDouglas Gregor } 1372e7ab3669SDouglas Gregor } 13735257fc63SDouglas Gregor 13745257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 13755257fc63SDouglas Gregor // Come up with a lazy way to do this. 1376e7ab3669SDouglas Gregor if (File) { 137759527666SDouglas Gregor if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) { 13785257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 137959527666SDouglas Gregor << FileName << OwningModule.getModule()->getFullModuleName(); 13805257fc63SDouglas Gregor HadError = true; 1381322f633cSDouglas Gregor } else if (Umbrella) { 1382322f633cSDouglas Gregor const DirectoryEntry *UmbrellaDir = File->getDir(); 138359527666SDouglas Gregor if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) { 1384322f633cSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 138559527666SDouglas Gregor << UmbrellaModule->getFullModuleName(); 1386322f633cSDouglas Gregor HadError = true; 13875257fc63SDouglas Gregor } else { 1388322f633cSDouglas Gregor // Record this umbrella header. 1389322f633cSDouglas Gregor Map.setUmbrellaHeader(ActiveModule, File); 1390322f633cSDouglas Gregor } 1391322f633cSDouglas Gregor } else { 1392322f633cSDouglas Gregor // Record this header. 139359527666SDouglas Gregor Map.addHeader(ActiveModule, File, Exclude); 13943ec6663bSDouglas Gregor 13953ec6663bSDouglas Gregor // If there is a builtin counterpart to this file, add it now. 13963ec6663bSDouglas Gregor if (BuiltinFile) 139759527666SDouglas Gregor Map.addHeader(ActiveModule, BuiltinFile, Exclude); 13985257fc63SDouglas Gregor } 13994b27a64bSDouglas Gregor } else if (!Exclude) { 14004b27a64bSDouglas Gregor // Ignore excluded header files. They're optional anyway. 14014b27a64bSDouglas Gregor 14025257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 1403524e33e1SDouglas Gregor << Umbrella << FileName; 14045257fc63SDouglas Gregor HadError = true; 14055257fc63SDouglas Gregor } 1406718292f2SDouglas Gregor } 1407718292f2SDouglas Gregor 1408524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration. 1409524e33e1SDouglas Gregor /// 1410524e33e1SDouglas Gregor /// umbrella-dir-declaration: 1411524e33e1SDouglas Gregor /// umbrella string-literal 1412524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 1413524e33e1SDouglas Gregor // Parse the directory name. 1414524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1415524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 1416524e33e1SDouglas Gregor << "umbrella"; 1417524e33e1SDouglas Gregor HadError = true; 1418524e33e1SDouglas Gregor return; 1419524e33e1SDouglas Gregor } 1420524e33e1SDouglas Gregor 1421524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 1422524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 1423524e33e1SDouglas Gregor 1424524e33e1SDouglas Gregor // Check whether we already have an umbrella. 1425524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 1426524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 1427524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 1428524e33e1SDouglas Gregor HadError = true; 1429524e33e1SDouglas Gregor return; 1430524e33e1SDouglas Gregor } 1431524e33e1SDouglas Gregor 1432524e33e1SDouglas Gregor // Look for this file. 1433524e33e1SDouglas Gregor const DirectoryEntry *Dir = 0; 1434524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 1435524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 1436524e33e1SDouglas Gregor else { 14372c1dd271SDylan Noblesmith SmallString<128> PathName; 1438524e33e1SDouglas Gregor PathName = Directory->getName(); 1439524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 1440524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 1441524e33e1SDouglas Gregor } 1442524e33e1SDouglas Gregor 1443524e33e1SDouglas Gregor if (!Dir) { 1444524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found) 1445524e33e1SDouglas Gregor << DirName; 1446524e33e1SDouglas Gregor HadError = true; 1447524e33e1SDouglas Gregor return; 1448524e33e1SDouglas Gregor } 1449524e33e1SDouglas Gregor 1450524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 1451524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 1452524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 1453524e33e1SDouglas Gregor HadError = true; 1454524e33e1SDouglas Gregor return; 1455524e33e1SDouglas Gregor } 1456524e33e1SDouglas Gregor 1457524e33e1SDouglas Gregor // Record this umbrella directory. 1458524e33e1SDouglas Gregor Map.setUmbrellaDir(ActiveModule, Dir); 1459524e33e1SDouglas Gregor } 1460524e33e1SDouglas Gregor 14612b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 14622b82c2a5SDouglas Gregor /// 14632b82c2a5SDouglas Gregor /// export-declaration: 14642b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 14652b82c2a5SDouglas Gregor /// 14662b82c2a5SDouglas Gregor /// wildcard-module-id: 14672b82c2a5SDouglas Gregor /// identifier 14682b82c2a5SDouglas Gregor /// '*' 14692b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 14702b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 14712b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 14722b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 14732b82c2a5SDouglas Gregor 14742b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 14752b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 14762b82c2a5SDouglas Gregor bool Wildcard = false; 14772b82c2a5SDouglas Gregor do { 14782b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 14792b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 14802b82c2a5SDouglas Gregor Tok.getLocation())); 14812b82c2a5SDouglas Gregor consumeToken(); 14822b82c2a5SDouglas Gregor 14832b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 14842b82c2a5SDouglas Gregor consumeToken(); 14852b82c2a5SDouglas Gregor continue; 14862b82c2a5SDouglas Gregor } 14872b82c2a5SDouglas Gregor 14882b82c2a5SDouglas Gregor break; 14892b82c2a5SDouglas Gregor } 14902b82c2a5SDouglas Gregor 14912b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 14922b82c2a5SDouglas Gregor Wildcard = true; 1493f5eedd05SDouglas Gregor consumeToken(); 14942b82c2a5SDouglas Gregor break; 14952b82c2a5SDouglas Gregor } 14962b82c2a5SDouglas Gregor 14972b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 14982b82c2a5SDouglas Gregor HadError = true; 14992b82c2a5SDouglas Gregor return; 15002b82c2a5SDouglas Gregor } while (true); 15012b82c2a5SDouglas Gregor 15022b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 15032b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 15042b82c2a5SDouglas Gregor }; 15052b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 15062b82c2a5SDouglas Gregor } 15072b82c2a5SDouglas Gregor 15086ddfca91SDouglas Gregor /// \brief Parse a link declaration. 15096ddfca91SDouglas Gregor /// 15106ddfca91SDouglas Gregor /// module-declaration: 15116ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 15126ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 15136ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 15146ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 15156ddfca91SDouglas Gregor 15166ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 15176ddfca91SDouglas Gregor bool IsFramework = false; 15186ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 15196ddfca91SDouglas Gregor consumeToken(); 15206ddfca91SDouglas Gregor IsFramework = true; 15216ddfca91SDouglas Gregor } 15226ddfca91SDouglas Gregor 15236ddfca91SDouglas Gregor // Parse the library name 15246ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 15256ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 15266ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 15276ddfca91SDouglas Gregor HadError = true; 15286ddfca91SDouglas Gregor return; 15296ddfca91SDouglas Gregor } 15306ddfca91SDouglas Gregor 15316ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 15326ddfca91SDouglas Gregor consumeToken(); 15336ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 15346ddfca91SDouglas Gregor IsFramework)); 15356ddfca91SDouglas Gregor } 15366ddfca91SDouglas Gregor 153735b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration. 153835b13eceSDouglas Gregor /// 153935b13eceSDouglas Gregor /// module-declaration: 154035b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 154135b13eceSDouglas Gregor /// 154235b13eceSDouglas Gregor /// config-macro-list: 154335b13eceSDouglas Gregor /// identifier (',' identifier)? 154435b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 154535b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 154635b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 154735b13eceSDouglas Gregor 154835b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 154935b13eceSDouglas Gregor if (ActiveModule->Parent) { 155035b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 155135b13eceSDouglas Gregor } 155235b13eceSDouglas Gregor 155335b13eceSDouglas Gregor // Parse the optional attributes. 155435b13eceSDouglas Gregor Attributes Attrs; 155535b13eceSDouglas Gregor parseOptionalAttributes(Attrs); 155635b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 155735b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 155835b13eceSDouglas Gregor } 155935b13eceSDouglas Gregor 156035b13eceSDouglas Gregor // If we don't have an identifier, we're done. 156135b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 156235b13eceSDouglas Gregor return; 156335b13eceSDouglas Gregor 156435b13eceSDouglas Gregor // Consume the first identifier. 156535b13eceSDouglas Gregor if (!ActiveModule->Parent) { 156635b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 156735b13eceSDouglas Gregor } 156835b13eceSDouglas Gregor consumeToken(); 156935b13eceSDouglas Gregor 157035b13eceSDouglas Gregor do { 157135b13eceSDouglas Gregor // If there's a comma, consume it. 157235b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 157335b13eceSDouglas Gregor break; 157435b13eceSDouglas Gregor consumeToken(); 157535b13eceSDouglas Gregor 157635b13eceSDouglas Gregor // We expect to see a macro name here. 157735b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 157835b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 157935b13eceSDouglas Gregor break; 158035b13eceSDouglas Gregor } 158135b13eceSDouglas Gregor 158235b13eceSDouglas Gregor // Consume the macro name. 158335b13eceSDouglas Gregor if (!ActiveModule->Parent) { 158435b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 158535b13eceSDouglas Gregor } 158635b13eceSDouglas Gregor consumeToken(); 158735b13eceSDouglas Gregor } while (true); 158835b13eceSDouglas Gregor } 158935b13eceSDouglas Gregor 1590*fb912657SDouglas Gregor /// \brief Format a module-id into a string. 1591*fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 1592*fb912657SDouglas Gregor std::string result; 1593*fb912657SDouglas Gregor { 1594*fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 1595*fb912657SDouglas Gregor 1596*fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 1597*fb912657SDouglas Gregor if (I) 1598*fb912657SDouglas Gregor OS << "."; 1599*fb912657SDouglas Gregor OS << Id[I].first; 1600*fb912657SDouglas Gregor } 1601*fb912657SDouglas Gregor } 1602*fb912657SDouglas Gregor 1603*fb912657SDouglas Gregor return result; 1604*fb912657SDouglas Gregor } 1605*fb912657SDouglas Gregor 1606*fb912657SDouglas Gregor /// \brief Parse a conflict declaration. 1607*fb912657SDouglas Gregor /// 1608*fb912657SDouglas Gregor /// module-declaration: 1609*fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 1610*fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 1611*fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 1612*fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 1613*fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 1614*fb912657SDouglas Gregor 1615*fb912657SDouglas Gregor // Parse the module-id. 1616*fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 1617*fb912657SDouglas Gregor return; 1618*fb912657SDouglas Gregor 1619*fb912657SDouglas Gregor // Parse the ','. 1620*fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 1621*fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 1622*fb912657SDouglas Gregor << SourceRange(ConflictLoc); 1623*fb912657SDouglas Gregor return; 1624*fb912657SDouglas Gregor } 1625*fb912657SDouglas Gregor consumeToken(); 1626*fb912657SDouglas Gregor 1627*fb912657SDouglas Gregor // Parse the message. 1628*fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1629*fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 1630*fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 1631*fb912657SDouglas Gregor return; 1632*fb912657SDouglas Gregor } 1633*fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 1634*fb912657SDouglas Gregor consumeToken(); 1635*fb912657SDouglas Gregor 1636*fb912657SDouglas Gregor // Add this unresolved conflict. 1637*fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 1638*fb912657SDouglas Gregor } 1639*fb912657SDouglas Gregor 16406ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules). 16419194a91dSDouglas Gregor /// 16429194a91dSDouglas Gregor /// module-declaration: 16439194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 16449194a91dSDouglas Gregor /// { inferred-module-member* } 16459194a91dSDouglas Gregor /// 16469194a91dSDouglas Gregor /// inferred-module-member: 16479194a91dSDouglas Gregor /// 'export' '*' 16489194a91dSDouglas Gregor /// 'exclude' identifier 16499194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 165073441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 165173441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 165273441091SDouglas Gregor bool Failed = false; 165373441091SDouglas Gregor 165473441091SDouglas Gregor // Inferred modules must be submodules. 16559194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 165673441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 165773441091SDouglas Gregor Failed = true; 165873441091SDouglas Gregor } 165973441091SDouglas Gregor 16609194a91dSDouglas Gregor if (ActiveModule) { 1661524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 1662524e33e1SDouglas Gregor if (!Failed && !ActiveModule->getUmbrellaDir()) { 166373441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 166473441091SDouglas Gregor Failed = true; 166573441091SDouglas Gregor } 166673441091SDouglas Gregor 166773441091SDouglas Gregor // Check for redefinition of an inferred module. 1668dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 166973441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 1670dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 1671dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 167273441091SDouglas Gregor diag::note_mmap_prev_definition); 167373441091SDouglas Gregor Failed = true; 167473441091SDouglas Gregor } 167573441091SDouglas Gregor 16769194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 16779194a91dSDouglas Gregor if (Framework) { 16789194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 16799194a91dSDouglas Gregor Framework = false; 16809194a91dSDouglas Gregor } 16819194a91dSDouglas Gregor } else if (Explicit) { 16829194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 16839194a91dSDouglas Gregor Explicit = false; 16849194a91dSDouglas Gregor } 16859194a91dSDouglas Gregor 168673441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 168773441091SDouglas Gregor if (Failed) { 168873441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 168973441091SDouglas Gregor consumeToken(); 169073441091SDouglas Gregor skipUntil(MMToken::RBrace); 169173441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 169273441091SDouglas Gregor consumeToken(); 169373441091SDouglas Gregor } 169473441091SDouglas Gregor HadError = true; 169573441091SDouglas Gregor return; 169673441091SDouglas Gregor } 169773441091SDouglas Gregor 16989194a91dSDouglas Gregor // Parse optional attributes. 16994442605fSBill Wendling Attributes Attrs; 17009194a91dSDouglas Gregor parseOptionalAttributes(Attrs); 17019194a91dSDouglas Gregor 17029194a91dSDouglas Gregor if (ActiveModule) { 170373441091SDouglas Gregor // Note that we have an inferred submodule. 1704dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 1705dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 1706dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 17079194a91dSDouglas Gregor } else { 17089194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 17099194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 17109194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferSystemModules = Attrs.IsSystem; 17119194a91dSDouglas Gregor } 171273441091SDouglas Gregor 171373441091SDouglas Gregor // Parse the opening brace. 171473441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 171573441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 171673441091SDouglas Gregor HadError = true; 171773441091SDouglas Gregor return; 171873441091SDouglas Gregor } 171973441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 172073441091SDouglas Gregor 172173441091SDouglas Gregor // Parse the body of the inferred submodule. 172273441091SDouglas Gregor bool Done = false; 172373441091SDouglas Gregor do { 172473441091SDouglas Gregor switch (Tok.Kind) { 172573441091SDouglas Gregor case MMToken::EndOfFile: 172673441091SDouglas Gregor case MMToken::RBrace: 172773441091SDouglas Gregor Done = true; 172873441091SDouglas Gregor break; 172973441091SDouglas Gregor 17309194a91dSDouglas Gregor case MMToken::ExcludeKeyword: { 17319194a91dSDouglas Gregor if (ActiveModule) { 17329194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 1733162405daSDouglas Gregor << (ActiveModule != 0); 17349194a91dSDouglas Gregor consumeToken(); 17359194a91dSDouglas Gregor break; 17369194a91dSDouglas Gregor } 17379194a91dSDouglas Gregor 17389194a91dSDouglas Gregor consumeToken(); 17399194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 17409194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 17419194a91dSDouglas Gregor break; 17429194a91dSDouglas Gregor } 17439194a91dSDouglas Gregor 17449194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 17459194a91dSDouglas Gregor .push_back(Tok.getString()); 17469194a91dSDouglas Gregor consumeToken(); 17479194a91dSDouglas Gregor break; 17489194a91dSDouglas Gregor } 17499194a91dSDouglas Gregor 17509194a91dSDouglas Gregor case MMToken::ExportKeyword: 17519194a91dSDouglas Gregor if (!ActiveModule) { 17529194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 1753162405daSDouglas Gregor << (ActiveModule != 0); 17549194a91dSDouglas Gregor consumeToken(); 17559194a91dSDouglas Gregor break; 17569194a91dSDouglas Gregor } 17579194a91dSDouglas Gregor 175873441091SDouglas Gregor consumeToken(); 175973441091SDouglas Gregor if (Tok.is(MMToken::Star)) 1760dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 176173441091SDouglas Gregor else 176273441091SDouglas Gregor Diags.Report(Tok.getLocation(), 176373441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 176473441091SDouglas Gregor consumeToken(); 176573441091SDouglas Gregor break; 176673441091SDouglas Gregor 176773441091SDouglas Gregor case MMToken::ExplicitKeyword: 176873441091SDouglas Gregor case MMToken::ModuleKeyword: 176973441091SDouglas Gregor case MMToken::HeaderKeyword: 177073441091SDouglas Gregor case MMToken::UmbrellaKeyword: 177173441091SDouglas Gregor default: 17729194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 1773162405daSDouglas Gregor << (ActiveModule != 0); 177473441091SDouglas Gregor consumeToken(); 177573441091SDouglas Gregor break; 177673441091SDouglas Gregor } 177773441091SDouglas Gregor } while (!Done); 177873441091SDouglas Gregor 177973441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 178073441091SDouglas Gregor consumeToken(); 178173441091SDouglas Gregor else { 178273441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 178373441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 178473441091SDouglas Gregor HadError = true; 178573441091SDouglas Gregor } 178673441091SDouglas Gregor } 178773441091SDouglas Gregor 17889194a91dSDouglas Gregor /// \brief Parse optional attributes. 17899194a91dSDouglas Gregor /// 17909194a91dSDouglas Gregor /// attributes: 17919194a91dSDouglas Gregor /// attribute attributes 17929194a91dSDouglas Gregor /// attribute 17939194a91dSDouglas Gregor /// 17949194a91dSDouglas Gregor /// attribute: 17959194a91dSDouglas Gregor /// [ identifier ] 17969194a91dSDouglas Gregor /// 17979194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 17989194a91dSDouglas Gregor /// 17999194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 18004442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 18019194a91dSDouglas Gregor bool HadError = false; 18029194a91dSDouglas Gregor 18039194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 18049194a91dSDouglas Gregor // Consume the '['. 18059194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 18069194a91dSDouglas Gregor 18079194a91dSDouglas Gregor // Check whether we have an attribute name here. 18089194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 18099194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 18109194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 18119194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 18129194a91dSDouglas Gregor consumeToken(); 18139194a91dSDouglas Gregor HadError = true; 18149194a91dSDouglas Gregor } 18159194a91dSDouglas Gregor 18169194a91dSDouglas Gregor // Decode the attribute name. 18179194a91dSDouglas Gregor AttributeKind Attribute 18189194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 181935b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 18209194a91dSDouglas Gregor .Case("system", AT_system) 18219194a91dSDouglas Gregor .Default(AT_unknown); 18229194a91dSDouglas Gregor switch (Attribute) { 18239194a91dSDouglas Gregor case AT_unknown: 18249194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 18259194a91dSDouglas Gregor << Tok.getString(); 18269194a91dSDouglas Gregor break; 18279194a91dSDouglas Gregor 18289194a91dSDouglas Gregor case AT_system: 18299194a91dSDouglas Gregor Attrs.IsSystem = true; 18309194a91dSDouglas Gregor break; 183135b13eceSDouglas Gregor 183235b13eceSDouglas Gregor case AT_exhaustive: 183335b13eceSDouglas Gregor Attrs.IsExhaustive = true; 183435b13eceSDouglas Gregor break; 18359194a91dSDouglas Gregor } 18369194a91dSDouglas Gregor consumeToken(); 18379194a91dSDouglas Gregor 18389194a91dSDouglas Gregor // Consume the ']'. 18399194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 18409194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 18419194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 18429194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 18439194a91dSDouglas Gregor HadError = true; 18449194a91dSDouglas Gregor } 18459194a91dSDouglas Gregor 18469194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 18479194a91dSDouglas Gregor consumeToken(); 18489194a91dSDouglas Gregor } 18499194a91dSDouglas Gregor 18509194a91dSDouglas Gregor return HadError; 18519194a91dSDouglas Gregor } 18529194a91dSDouglas Gregor 18537033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence 18547033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null. 18557033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() { 18567033127bSDouglas Gregor for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) { 18577033127bSDouglas Gregor // If we have an umbrella directory, use that. 18587033127bSDouglas Gregor if (Mod->hasUmbrellaDir()) 18597033127bSDouglas Gregor return Mod->getUmbrellaDir(); 18607033127bSDouglas Gregor 18617033127bSDouglas Gregor // If we have a framework directory, stop looking. 18627033127bSDouglas Gregor if (Mod->IsFramework) 18637033127bSDouglas Gregor return 0; 18647033127bSDouglas Gregor } 18657033127bSDouglas Gregor 18667033127bSDouglas Gregor return 0; 18677033127bSDouglas Gregor } 18687033127bSDouglas Gregor 1869718292f2SDouglas Gregor /// \brief Parse a module map file. 1870718292f2SDouglas Gregor /// 1871718292f2SDouglas Gregor /// module-map-file: 1872718292f2SDouglas Gregor /// module-declaration* 1873718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 1874718292f2SDouglas Gregor do { 1875718292f2SDouglas Gregor switch (Tok.Kind) { 1876718292f2SDouglas Gregor case MMToken::EndOfFile: 1877718292f2SDouglas Gregor return HadError; 1878718292f2SDouglas Gregor 1879e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 1880718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1881755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 1882718292f2SDouglas Gregor parseModuleDecl(); 1883718292f2SDouglas Gregor break; 1884718292f2SDouglas Gregor 18851fb5c3a6SDouglas Gregor case MMToken::Comma: 188635b13eceSDouglas Gregor case MMToken::ConfigMacros: 1887*fb912657SDouglas Gregor case MMToken::Conflict: 188859527666SDouglas Gregor case MMToken::ExcludeKeyword: 18892b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 1890718292f2SDouglas Gregor case MMToken::HeaderKeyword: 1891718292f2SDouglas Gregor case MMToken::Identifier: 1892718292f2SDouglas Gregor case MMToken::LBrace: 18936ddfca91SDouglas Gregor case MMToken::LinkKeyword: 1894a686e1b0SDouglas Gregor case MMToken::LSquare: 18952b82c2a5SDouglas Gregor case MMToken::Period: 1896718292f2SDouglas Gregor case MMToken::RBrace: 1897a686e1b0SDouglas Gregor case MMToken::RSquare: 18981fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 18992b82c2a5SDouglas Gregor case MMToken::Star: 1900718292f2SDouglas Gregor case MMToken::StringLiteral: 1901718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 1902718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1903718292f2SDouglas Gregor HadError = true; 1904718292f2SDouglas Gregor consumeToken(); 1905718292f2SDouglas Gregor break; 1906718292f2SDouglas Gregor } 1907718292f2SDouglas Gregor } while (true); 1908718292f2SDouglas Gregor } 1909718292f2SDouglas Gregor 1910718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 19114ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 19124ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 19134ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 19144ddf2221SDouglas Gregor return Known->second; 19154ddf2221SDouglas Gregor 191689929282SDouglas Gregor assert(Target != 0 && "Missing target information"); 1917718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 1918718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 1919718292f2SDouglas Gregor if (!Buffer) 19204ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 1921718292f2SDouglas Gregor 1922718292f2SDouglas Gregor // Parse this module map file. 19231fb5c3a6SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts); 19241fb5c3a6SDouglas Gregor Diags->getClient()->BeginSourceFile(MMapLangOpts); 1925bc10b9fbSDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(), 19263ec6663bSDouglas Gregor BuiltinIncludeDir); 1927718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 1928718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 19294ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 1930718292f2SDouglas Gregor return Result; 1931718292f2SDouglas Gregor } 1932