summaryrefslogtreecommitdiffstats
path: root/clang/lib/Lex
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-12-02 00:08:08 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-12-02 00:08:08 +0000
commit3c1a41ad9969ae4e3353f5984d66af85ce56cf9a (patch)
treef19e3452dbc34c152accbcee5057286a353da704 /clang/lib/Lex
parent4cdf4eba74df1c2a679931716fc630fd484bdb3c (diff)
downloadbcm5719-llvm-3c1a41ad9969ae4e3353f5984d66af85ce56cf9a.tar.gz
bcm5719-llvm-3c1a41ad9969ae4e3353f5984d66af85ce56cf9a.zip
[modules] Track how 'header' directives were written in module map files,
rather than trying to extract this information from the FileEntry after the fact. This has a number of beneficial effects. For instance, diagnostic messages for failed module builds give a path relative to the "module root" rather than an absolute file path, and the contents of the module includes file is no longer dependent on what files the including TU happened to inspect prior to triggering the module build. llvm-svn: 223095
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