summaryrefslogtreecommitdiffstats
path: root/clang/lib/Lex
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Lex')
-rw-r--r--clang/lib/Lex/HeaderSearch.cpp17
-rw-r--r--clang/lib/Lex/ModuleMap.cpp109
-rw-r--r--clang/lib/Lex/PPDirectives.cpp22
-rw-r--r--clang/lib/Lex/Preprocessor.cpp2
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) {
OpenPOWER on IntegriCloud