diff options
Diffstat (limited to 'clang/lib/Lex')
-rw-r--r-- | clang/lib/Lex/HeaderSearch.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 109 | ||||
-rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Lex/Preprocessor.cpp | 2 |
4 files changed, 93 insertions, 57 deletions
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 125fe260e13..131f6aa09cf 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -624,11 +624,20 @@ const FileEntry *HeaderSearch::LookupFile( // FIXME: We don't cache the result of getFileInfo across the call to // getFileAndSuggestModule, because it's a reference to an element of // a container that could be reallocated across this call. + // + // FIXME: If we have no includer, that means we're processing a #include + // from a module build. We should treat this as a system header if we're + // building a [system] module. bool IncluderIsSystemHeader = - getFileInfo(Includer).DirInfo != SrcMgr::C_User; + Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User; if (const FileEntry *FE = getFileAndSuggestModule( *this, TmpDir.str(), IncluderAndDir.second, IncluderIsSystemHeader, SuggestedModule)) { + if (!Includer) { + assert(First && "only first includer can have no file"); + return FE; + } + // Leave CurDir unset. // This file is a system header or C++ unfriendly if the old file is. // @@ -770,7 +779,7 @@ const FileEntry *HeaderSearch::LookupFile( // a header in a framework that is currently being built, and we couldn't // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where // "Foo" is the name of the framework in which the including header was found. - if (!Includers.empty() && !isAngled && + if (!Includers.empty() && Includers.front().first && !isAngled && Filename.find('/') == StringRef::npos) { HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front().first); if (IncludingHFI.IndexHeaderMapHeader) { @@ -1079,7 +1088,9 @@ bool HeaderSearch::hasModuleMap(StringRef FileName, return false; // Try to load the module map file in this directory. - switch (loadModuleMapFile(Dir, IsSystem, /*IsFramework*/false)) { + switch (loadModuleMapFile(Dir, IsSystem, + llvm::sys::path::extension(Dir->getName()) == + ".framework")) { case LMM_NewlyLoaded: case LMM_AlreadyLoaded: // Success. All of the directories we stepped through inherit this module diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 6a470ef886c..a270b56e6af 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -220,12 +220,14 @@ static bool violatesPrivateInclude(Module *RequestingModule, // as obtained from the lookup and as obtained from the module. // This check is not cheap, so enable it only for debugging. bool IsPrivate = false; - SmallVectorImpl<const FileEntry *> *HeaderList[] = - {&RequestedModule->PrivateHeaders, - &RequestedModule->PrivateTextualHeaders}; + SmallVectorImpl<Module::Header> *HeaderList[] = + {&RequestedModule->Headers[Module::HK_Private], + &RequestedModule->Headers[Module::HK_PrivateTextual]}; for (auto *Hdrs : HeaderList) IsPrivate |= - std::find(Hdrs->begin(), Hdrs->end(), IncFileEnt) != Hdrs->end(); + std::find_if(Hdrs->begin(), Hdrs->end(), [&](const Module::Header &H) { + return H.Entry == IncFileEnt; + }) != Hdrs->end(); assert(IsPrivate == IsPrivateRole && "inconsistent headers and roles"); #endif return IsPrivateRole && @@ -778,40 +780,40 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) { UmbrellaDirs[UmbrellaDir] = Mod; } -void ModuleMap::addHeader(Module *Mod, const FileEntry *Header, - ModuleHeaderRole Role) { +static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) { switch ((int)Role) { - default: - llvm_unreachable("unknown header role"); - case NormalHeader: - Mod->NormalHeaders.push_back(Header); - break; - case PrivateHeader: - Mod->PrivateHeaders.push_back(Header); - break; - case TextualHeader: - Mod->TextualHeaders.push_back(Header); - break; - case PrivateHeader | TextualHeader: - Mod->PrivateTextualHeaders.push_back(Header); - break; + default: llvm_unreachable("unknown header role"); + case ModuleMap::NormalHeader: + return Module::HK_Normal; + case ModuleMap::PrivateHeader: + return Module::HK_Private; + case ModuleMap::TextualHeader: + return Module::HK_Textual; + case ModuleMap::PrivateHeader | ModuleMap::TextualHeader: + return Module::HK_PrivateTextual; } +} +void ModuleMap::addHeader(Module *Mod, Module::Header Header, + ModuleHeaderRole Role) { if (!(Role & TextualHeader)) { bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule; - HeaderInfo.MarkFileModuleHeader(Header, Role, isCompilingModuleHeader); + HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, + isCompilingModuleHeader); } - Headers[Header].push_back(KnownHeader(Mod, Role)); -} + Headers[Header.Entry].push_back(KnownHeader(Mod, Role)); -void ModuleMap::excludeHeader(Module *Mod, const FileEntry *Header) { - Mod->ExcludedHeaders.push_back(Header); + Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header)); +} +void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { // Add this as a known header so we won't implicitly add it to any // umbrella directory module. // FIXME: Should we only exclude it from umbrella modules within the // specified module? - (void) Headers[Header]; + (void) Headers[Header.Entry]; + + Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); } const FileEntry * @@ -1447,6 +1449,7 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule->IsSystem = true; if (Attrs.IsExternC) ActiveModule->IsExternC = true; + ActiveModule->Directory = Directory; bool Done = false; do { @@ -1699,7 +1702,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, HadError = true; return; } - Module::HeaderDirective Header; + Module::UnresolvedHeaderDirective Header; Header.FileName = Tok.getString(); Header.FileNameLoc = consumeToken(); @@ -1714,33 +1717,39 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, // Look for this file. const FileEntry *File = nullptr; const FileEntry *BuiltinFile = nullptr; - SmallString<128> PathName; + SmallString<128> RelativePathName; if (llvm::sys::path::is_absolute(Header.FileName)) { - PathName = Header.FileName; - File = SourceMgr.getFileManager().getFile(PathName); + RelativePathName = Header.FileName; + File = SourceMgr.getFileManager().getFile(RelativePathName); } else { // Search for the header file within the search directory. - PathName = Directory->getName(); - unsigned PathLength = PathName.size(); + SmallString<128> FullPathName(Directory->getName()); + unsigned FullPathLength = FullPathName.size(); if (ActiveModule->isPartOfFramework()) { - appendSubframeworkPaths(ActiveModule, PathName); + appendSubframeworkPaths(ActiveModule, RelativePathName); // Check whether this file is in the public headers. - llvm::sys::path::append(PathName, "Headers", Header.FileName); - File = SourceMgr.getFileManager().getFile(PathName); + llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); + llvm::sys::path::append(FullPathName, RelativePathName.str()); + File = SourceMgr.getFileManager().getFile(FullPathName); if (!File) { // Check whether this file is in the private headers. - PathName.resize(PathLength); - llvm::sys::path::append(PathName, "PrivateHeaders", Header.FileName); - File = SourceMgr.getFileManager().getFile(PathName); + // FIXME: Should we retain the subframework paths here? + RelativePathName.clear(); + FullPathName.resize(FullPathLength); + llvm::sys::path::append(RelativePathName, "PrivateHeaders", + Header.FileName); + llvm::sys::path::append(FullPathName, RelativePathName.str()); + File = SourceMgr.getFileManager().getFile(FullPathName); } } else { // Lookup for normal headers. - llvm::sys::path::append(PathName, Header.FileName); - File = SourceMgr.getFileManager().getFile(PathName); - + llvm::sys::path::append(RelativePathName, Header.FileName); + llvm::sys::path::append(FullPathName, RelativePathName.str()); + File = SourceMgr.getFileManager().getFile(FullPathName); + // If this is a system module with a top-level header, this header // may have a counterpart (or replacement) in the set of headers // supplied by Clang. Find that builtin header. @@ -1750,18 +1759,19 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); llvm::sys::path::append(BuiltinPathName, Header.FileName); BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); - + // If Clang supplies this header but the underlying system does not, // just silently swap in our builtin version. Otherwise, we'll end // up adding both (later). if (!File && BuiltinFile) { File = BuiltinFile; + RelativePathName = BuiltinPathName; BuiltinFile = nullptr; } } } } - + // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. // Come up with a lazy way to do this. if (File) { @@ -1776,16 +1786,23 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, Map.setUmbrellaHeader(ActiveModule, File); } } else if (LeadingToken == MMToken::ExcludeKeyword) { - Map.excludeHeader(ActiveModule, File); + Map.excludeHeader(ActiveModule, + Module::Header{RelativePathName.str(), File}); } else { // If there is a builtin counterpart to this file, add it now, before // the "real" header, so we build the built-in one first when building // the module. if (BuiltinFile) - Map.addHeader(ActiveModule, BuiltinFile, Role); + // FIXME: Taking the name from the FileEntry is unstable and can give + // different results depending on how we've previously named that file + // in this build. + Map.addHeader(ActiveModule, + Module::Header{BuiltinFile->getName(), BuiltinFile}, + Role); // Record this header. - Map.addHeader(ActiveModule, File, Role); + Map.addHeader(ActiveModule, Module::Header{RelativePathName.str(), File}, + Role); } } else if (LeadingToken != MMToken::ExcludeKeyword) { // Ignore excluded header files. They're optional anyway. diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 04f3b29bd5b..0a46663d85d 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -550,14 +550,22 @@ const FileEntry *Preprocessor::LookupFile( const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID); // If there is no file entry associated with this file, it must be the - // predefines buffer. Any other file is not lexed with a normal lexer, so - // it won't be scanned for preprocessor directives. If we have the - // predefines buffer, resolve #include references (which come from the - // -include command line argument) from the current working directory - // instead of relative to the main file. + // predefines buffer or the module includes buffer. Any other file is not + // lexed with a normal lexer, so it won't be scanned for preprocessor + // directives. + // + // If we have the predefines buffer, resolve #include references (which come + // from the -include command line argument) from the current working + // directory instead of relative to the main file. + // + // If we have the module includes buffer, resolve #include references (which + // come from header declarations in the module map) relative to the module + // map file. if (!FileEnt) { - FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); - if (FileEnt) + if (FID == SourceMgr.getMainFileID() && MainFileDir) + Includers.push_back(std::make_pair(nullptr, MainFileDir)); + else if ((FileEnt = + SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()))) Includers.push_back(std::make_pair(FileEnt, FileMgr.getDirectory("."))); } else { Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir())); diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 5da54aea30f..63c9aec8554 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -71,7 +71,7 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, CodeComplete(nullptr), CodeCompletionFile(nullptr), CodeCompletionOffset(0), LastTokenWasAt(false), ModuleImportExpectsIdentifier(false), CodeCompletionReached(0), - SkipMainFilePreamble(0, true), CurPPLexer(nullptr), + MainFileDir(nullptr), SkipMainFilePreamble(0, true), CurPPLexer(nullptr), CurDirLookup(nullptr), CurLexerKind(CLK_Lexer), CurSubmodule(nullptr), Callbacks(nullptr), MacroArgCache(nullptr), Record(nullptr), MIChainHead(nullptr), DeserialMIChainHead(nullptr) { |