summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/Modules.rst7
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td4
-rw-r--r--include/clang/Basic/Module.h5
-rw-r--r--include/clang/Lex/DirectoryLookup.h5
-rw-r--r--include/clang/Lex/HeaderSearch.h25
-rw-r--r--include/clang/Lex/ModuleMap.h40
-rw-r--r--include/clang/Lex/Preprocessor.h5
-rw-r--r--include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--lib/Basic/Module.cpp11
-rw-r--r--lib/Frontend/FrontendActions.cpp5
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp2
-rw-r--r--lib/Lex/HeaderSearch.cpp20
-rw-r--r--lib/Lex/ModuleMap.cpp95
-rw-r--r--lib/Lex/PPDirectives.cpp45
-rw-r--r--lib/Lex/PPMacroExpansion.cpp3
-rw-r--r--lib/Lex/Pragma.cpp4
-rw-r--r--lib/Serialization/ASTReader.cpp19
-rw-r--r--lib/Serialization/ASTWriter.cpp21
18 files changed, 229 insertions, 91 deletions
diff --git a/docs/Modules.rst b/docs/Modules.rst
index fdf597a5a9..cd430a2ad2 100644
--- a/docs/Modules.rst
+++ b/docs/Modules.rst
@@ -231,8 +231,8 @@ Module map files use a simplified form of the C99 lexer, with the same rules for
``config_macros`` ``export`` ``module``
``conflict`` ``framework`` ``requires``
- ``exclude`` ``header`` ``umbrella``
- ``explicit`` ``link``
+ ``exclude`` ``header`` ``private``
+ ``explicit`` ``link`` ``umbrella``
Module map file
---------------
@@ -360,6 +360,7 @@ A header declaration specifies that a particular header is associated with the e
*header-declaration*:
``umbrella``:sub:`opt` ``header`` *string-literal*
+ ``private`` ``header`` *string-literal*
``exclude`` ``header`` *string-literal*
A header declaration that does not contain ``exclude`` specifies a header that contributes to the enclosing module. Specifically, when the module is built, the named header will be parsed and its declarations will be (logically) placed into the enclosing submodule.
@@ -372,6 +373,8 @@ A header with the ``umbrella`` specifier is called an umbrella header. An umbrel
``-Wincomplete-umbrella`` warning option to ask Clang to complain
about headers not covered by the umbrella header or the module map.
+A header with the ``private`` specifier may not be included from outside the module itself.
+
A header with the ``exclude`` specifier is excluded from the module. It will not be included when the module is built, nor will it be considered to be part of the module.
**Example**: The C header ``assert.h`` is an excellent candidate for an excluded header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings).
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index 49acbd5a31..8d1d18bb97 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -585,7 +585,9 @@ def warn_forgotten_module_header : Warning<
InGroup<IncompleteModule>, DefaultIgnore;
def err_expected_id_building_module : Error<
"expected a module name in '__building_module' expression">;
-
+def error_use_of_private_header_outside_module : Error<
+ "use of private header from outside its module: '%0'">;
+
def warn_header_guard : Warning<
"%0 is used as a header guard here, followed by #define of a different macro">,
InGroup<DiagGroup<"header-guard">>;
diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h
index d2a43f0219..8d7913d709 100644
--- a/include/clang/Basic/Module.h
+++ b/include/clang/Basic/Module.h
@@ -77,11 +77,14 @@ private:
public:
/// \brief The headers that are part of this module.
- SmallVector<const FileEntry *, 2> Headers;
+ SmallVector<const FileEntry *, 2> NormalHeaders;
/// \brief The headers that are explicitly excluded from this module.
SmallVector<const FileEntry *, 2> ExcludedHeaders;
+ /// \brief The headers that are private to this module.
+ llvm::SmallVector<const FileEntry *, 2> PrivateHeaders;
+
/// \brief The set of language features required to use this module.
///
/// If any of these features is not present, the \c IsAvailable bit
diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h
index 261dfabc0f..6675ea22a7 100644
--- a/include/clang/Lex/DirectoryLookup.h
+++ b/include/clang/Lex/DirectoryLookup.h
@@ -16,6 +16,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/ModuleMap.h"
namespace clang {
class HeaderMap;
@@ -158,7 +159,7 @@ public:
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework) const;
private:
@@ -166,7 +167,7 @@ private:
StringRef Filename, HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemHeader) const;
};
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 838df6831a..4e54fe0b2c 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -56,6 +56,10 @@ struct HeaderFileInfo {
/// \brief Whether this header is part of the module that we are building.
unsigned isCompilingModuleHeader : 1;
+
+ /// \brief Whether this header is part of the module that we are building.
+ /// This is an instance of ModuleMap::ModuleHeaderRole.
+ unsigned HeaderRole : 2;
/// \brief Whether this structure is considered to already have been
/// "resolved", meaning that it was loaded from the external source.
@@ -97,6 +101,7 @@ struct HeaderFileInfo {
HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
+ HeaderRole(ModuleMap::NormalHeader),
Resolved(false), IndexHeaderMapHeader(false),
NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {}
@@ -110,6 +115,16 @@ struct HeaderFileInfo {
return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
ControllingMacroID;
}
+
+ /// \brief Get the HeaderRole properly typed.
+ ModuleMap::ModuleHeaderRole getHeaderRole() const {
+ return static_cast<ModuleMap::ModuleHeaderRole>(HeaderRole);
+ }
+
+ /// \brief Set the HeaderRole properly typed.
+ void setHeaderRole(ModuleMap::ModuleHeaderRole Role) {
+ HeaderRole = Role;
+ }
};
/// \brief An external source of header file information, which may supply
@@ -357,7 +372,7 @@ public:
const FileEntry *CurFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache = false);
/// \brief Look up a subframework for the specified \#include file.
@@ -371,7 +386,7 @@ public:
const FileEntry *RelativeFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule);
+ ModuleMap::KnownHeader *SuggestedModule);
/// \brief Look up the specified framework name in our framework cache.
/// \returns The DirectoryEntry it is in if we know, null otherwise.
@@ -408,7 +423,9 @@ public:
}
/// \brief Mark the specified file as part of a module.
- void MarkFileModuleHeader(const FileEntry *File, bool IsCompiledModuleHeader);
+ void MarkFileModuleHeader(const FileEntry *File,
+ ModuleMap::ModuleHeaderRole Role,
+ bool IsCompiledModuleHeader);
/// \brief Increment the count for the number of times the specified
/// FileEntry has been entered.
@@ -484,7 +501,7 @@ public:
/// \brief Retrieve the module that corresponds to the given file, if any.
///
/// \param File The header that we wish to map to a module.
- Module *findModuleForHeader(const FileEntry *File) const;
+ ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File) const;
/// \brief Read the contents of the given module map file.
///
diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h
index b33b9e5ba6..924e696672 100644
--- a/include/clang/Lex/ModuleMap.h
+++ b/include/clang/Lex/ModuleMap.h
@@ -58,24 +58,40 @@ class ModuleMap {
/// \brief The top-level modules that are known.
llvm::StringMap<Module *> Modules;
+public:
+ /// \brief Describes the role of a module header.
+ enum ModuleHeaderRole {
+ /// \brief This header is normally included in the module.
+ NormalHeader,
+ /// \brief This header is included but private.
+ PrivateHeader,
+ /// \brief This header is explicitly excluded from the module.
+ ExcludedHeader
+ // Caution: Adding an enumerator needs other changes.
+ // Adjust the number of bits for KnownHeader::Storage.
+ // Adjust the bitfield HeaderFileInfo::HeaderRole size.
+ // Adjust the HeaderFileInfoTrait::ReadData streaming.
+ // Adjust the HeaderFileInfoTrait::EmitData streaming.
+ };
+
/// \brief A header that is known to reside within a given module,
/// whether it was included or excluded.
class KnownHeader {
- llvm::PointerIntPair<Module *, 1, bool> Storage;
+ llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage;
public:
- KnownHeader() : Storage(0, false) { }
- KnownHeader(Module *M, bool Excluded) : Storage(M, Excluded) { }
+ KnownHeader() : Storage(0, NormalHeader) { }
+ KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { }
/// \brief Retrieve the module the header is stored in.
Module *getModule() const { return Storage.getPointer(); }
- /// \brief Whether this header is explicitly excluded from the module.
- bool isExcluded() const { return Storage.getInt(); }
+ /// \brief The role of this header within the module.
+ ModuleHeaderRole getRole() const { return Storage.getInt(); }
/// \brief Whether this header is available in the module.
bool isAvailable() const {
- return !isExcluded() && getModule()->isAvailable();
+ return getRole() != ExcludedHeader && getModule()->isAvailable();
}
// \brief Whether this known header is valid (i.e., it has an
@@ -83,6 +99,7 @@ class ModuleMap {
LLVM_EXPLICIT operator bool() const { return Storage.getPointer() != 0; }
};
+private:
typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap;
/// \brief Mapping from each header to the module that owns the contents of
@@ -185,9 +202,10 @@ public:
///
/// \param File The header file that is likely to be included.
///
- /// \returns The module that owns the given header file, or null to indicate
+ /// \returns The module KnownHeader, which provides the module that owns the
+ /// given header file. The KnownHeader is default constructed to indicate
/// that no module owns this header file.
- Module *findModuleForHeader(const FileEntry *File);
+ KnownHeader findModuleForHeader(const FileEntry *File);
/// \brief Determine whether the given header is part of a module
/// marked 'unavailable'.
@@ -310,9 +328,9 @@ public:
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir);
/// \brief Adds this header to the given module.
- /// \param Excluded Whether this header is explicitly excluded from the
- /// module; otherwise, it's included in the module.
- void addHeader(Module *Mod, const FileEntry *Header, bool Excluded);
+ /// \param Role The role of the header wrt the module.
+ void addHeader(Module *Mod, const FileEntry *Header,
+ ModuleHeaderRole Role);
/// \brief Parse the given module map file, and record any modules we
/// encounter.
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index e993ce762f..60051ec112 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -20,6 +20,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/PTHLexer.h"
#include "clang/Lex/PTHManager.h"
@@ -1227,12 +1228,12 @@ public:
///
/// Returns null on failure. \p isAngled indicates whether the file
/// reference is for system \#include's or not (i.e. using <> instead of "").
- const FileEntry *LookupFile(StringRef Filename,
+ const FileEntry *LookupFile(SourceLocation FilenameLoc, StringRef Filename,
bool isAngled, const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache = false);
/// GetCurLookup - The DirectoryLookup structure used to find the current
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index b6ab2d8347..651b4a9df2 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -623,7 +623,9 @@ namespace clang {
/// \brief Specifies a configuration macro for this module.
SUBMODULE_CONFIG_MACRO = 11,
/// \brief Specifies a conflict with another module.
- SUBMODULE_CONFLICT = 12
+ SUBMODULE_CONFLICT = 12,
+ /// \brief Specifies a header that is private to this submodule.
+ SUBMODULE_PRIVATE_HEADER = 13
};
/// \brief Record types used within a comments block.
diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 13518cde66..8ac098ca79 100644
--- a/lib/Basic/Module.cpp
+++ b/lib/Basic/Module.cpp
@@ -293,10 +293,10 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS << "\n";
}
- for (unsigned I = 0, N = Headers.size(); I != N; ++I) {
+ for (unsigned I = 0, N = NormalHeaders.size(); I != N; ++I) {
OS.indent(Indent + 2);
OS << "header \"";
- OS.write_escaped(Headers[I]->getName());
+ OS.write_escaped(NormalHeaders[I]->getName());
OS << "\"\n";
}
@@ -306,6 +306,13 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
OS.write_escaped(ExcludedHeaders[I]->getName());
OS << "\"\n";
}
+
+ for (unsigned I = 0, N = PrivateHeaders.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "private header \"";
+ OS.write_escaped(PrivateHeaders[I]->getName());
+ OS << "\"\n";
+ }
for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end();
MI != MIEnd; ++MI)
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 5c7567fa8c..91eccbb26f 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -172,11 +172,12 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
return;
// Add includes for each of these headers.
- for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
- const FileEntry *Header = Module->Headers[I];
+ for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) {
+ const FileEntry *Header = Module->NormalHeaders[I];
Module->addTopHeader(Header);
addHeaderInclude(Header, Includes, LangOpts);
}
+ // Note that Module->PrivateHeaders will not be a TopHeader.
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
Module->addTopHeader(UmbrellaHeader);
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index 46745b6b9a..efe6005ed7 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -371,7 +371,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
// Lookup file via Preprocessor, like a #include.
const DirectoryLookup *CurDir;
- const FileEntry *FE = PP->LookupFile(Filename, false, NULL, CurDir,
+ const FileEntry *FE = PP->LookupFile(Pos, Filename, false, NULL, CurDir,
NULL, NULL, 0);
if (!FE) {
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 8a99ed2988..d2bc5ad5e5 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -223,7 +223,7 @@ const FileEntry *DirectoryLookup::LookupFile(
HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework) const {
InUserSpecifiedSystemFramework = false;
@@ -337,7 +337,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
HeaderSearch &HS,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework) const
{
FileManager &FileMgr = HS.getFileMgr();
@@ -496,11 +496,11 @@ const FileEntry *HeaderSearch::LookupFile(
const FileEntry *CurFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache)
{
if (SuggestedModule)
- *SuggestedModule = 0;
+ *SuggestedModule = ModuleMap::KnownHeader();
// If 'Filename' is absolute, check to see if it exists and no searching.
if (llvm::sys::path::is_absolute(Filename)) {
@@ -676,7 +676,7 @@ LookupSubframeworkHeader(StringRef Filename,
const FileEntry *ContextFileEnt,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule) {
+ ModuleMap::KnownHeader *SuggestedModule) {
assert(ContextFileEnt && "No context file?");
// Framework names must have a '/' in the filename. Find it.
@@ -867,6 +867,7 @@ bool HeaderSearch::isFileMultipleIncludeGuarded(const FileEntry *File) {
}
void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
+ ModuleMap::ModuleHeaderRole Role,
bool isCompilingModuleHeader) {
if (FE->getUID() >= FileInfo.size())
FileInfo.resize(FE->getUID()+1);
@@ -874,6 +875,7 @@ void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
HeaderFileInfo &HFI = FileInfo[FE->getUID()];
HFI.isModuleHeader = true;
HFI.isCompilingModuleHeader = isCompilingModuleHeader;
+ HFI.setHeaderRole(Role);
}
bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
@@ -966,16 +968,14 @@ bool HeaderSearch::hasModuleMap(StringRef FileName,
} while (true);
}
-Module *HeaderSearch::findModuleForHeader(const FileEntry *File) const {
+ModuleMap::KnownHeader
+HeaderSearch::findModuleForHeader(const FileEntry *File) const {
if (ExternalSource) {
// Make sure the external source has handled header info about this file,
// which includes whether the file is part of a module.
(void)getFileInfo(File);
}
- if (Module *Mod = ModMap.findModuleForHeader(File))
- return Mod;
-
- return 0;
+ return ModMap.findModuleForHeader(File);
}
bool HeaderSearch::loadModuleMapFile(const FileEntry *File) {
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index acb5694191..f46a87abc9 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -168,14 +168,14 @@ static bool isBuiltinHeader(StringRef FileName) {
.Default(false);
}
-Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
+ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
HeadersMap::iterator Known = Headers.find(File);
if (Known != Headers.end()) {
// If a header is not available, don't report that it maps to anything.
if (!Known->second.isAvailable())
- return 0;
+ return KnownHeader();
- return Known->second.getModule();
+ return Known->second;
}
// If we've found a builtin header within Clang's builtin include directory,
@@ -190,9 +190,9 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
if (Known != Headers.end()) {
// If a header is not available, don't report that it maps to anything.
if (!Known->second.isAvailable())
- return 0;
+ return KnownHeader();
- return Known->second.getModule();
+ return Known->second;
}
}
@@ -262,14 +262,14 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
UmbrellaDirs[SkippedDirs[I]] = Result;
}
- Headers[File] = KnownHeader(Result, /*Excluded=*/false);
+ Headers[File] = KnownHeader(Result, NormalHeader);
// If a header corresponds to an unavailable module, don't report
// that it maps to anything.
if (!Result->isAvailable())
- return 0;
+ return KnownHeader();
- return Result;
+ return Headers[File];
}
SkippedDirs.push_back(Dir);
@@ -283,7 +283,7 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Dir = SourceMgr->getFileManager().getDirectory(DirName);
} while (Dir);
- return 0;
+ return KnownHeader();
}
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
@@ -527,7 +527,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
// umbrella header "umbrella-header-name"
Result->Umbrella = UmbrellaHeader;
- Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
+ Headers[UmbrellaHeader] = KnownHeader(Result, NormalHeader);
UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
// export *
@@ -593,7 +593,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
}
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
- Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
+ Headers[UmbrellaHeader] = KnownHeader(Mod, NormalHeader);
Mod->Umbrella = UmbrellaHeader;
UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
}
@@ -604,15 +604,18 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
}
void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
- bool Excluded) {
- if (Excluded) {
+ ModuleHeaderRole Role) {
+ if (Role == ExcludedHeader) {
Mod->ExcludedHeaders.push_back(Header);
} else {
- Mod->Headers.push_back(Header);
+ if (Role == PrivateHeader)
+ Mod->PrivateHeaders.push_back(Header);
+ else
+ Mod->NormalHeaders.push_back(Header);
bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
- HeaderInfo.MarkFileModuleHeader(Header, isCompilingModuleHeader);
+ HeaderInfo.MarkFileModuleHeader(Header, Role, isCompilingModuleHeader);
}
- Headers[Header] = KnownHeader(Mod, Excluded);
+ Headers[Header] = KnownHeader(Mod, Role);
}
const FileEntry *
@@ -688,7 +691,7 @@ Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
while (const FileEntry *ExpansionFile
= SrcMgr.getFileEntryForID(ExpansionFileID)) {
// Find the module that owns this header (if any).
- if (Module *Mod = findModuleForHeader(ExpansionFile))
+ if (Module *Mod = findModuleForHeader(ExpansionFile).getModule())
return Mod;
// No module owns this header, so look up the inclusion chain to see if
@@ -724,6 +727,7 @@ namespace clang {
LinkKeyword,
ModuleKeyword,
Period,
+ PrivateKeyword,
UmbrellaKeyword,
RequiresKeyword,
Star,
@@ -809,7 +813,8 @@ namespace clang {
bool parseModuleId(ModuleId &Id);
void parseModuleDecl();
void parseRequiresDecl();
- void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
+ void parseHeaderDecl(clang::MMToken::TokenKind,
+ SourceLocation LeadingLoc);
void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
void parseExportDecl();
void parseLinkDecl();
@@ -861,6 +866,7 @@ retry:
.Case("header", MMToken::HeaderKeyword)
.Case("link", MMToken::LinkKeyword)
.Case("module", MMToken::ModuleKeyword)
+ .Case("private", MMToken::PrivateKeyword)
.Case("requires", MMToken::RequiresKeyword)
.Case("umbrella", MMToken::UmbrellaKeyword)
.Default(MMToken::Identifier);
@@ -1200,7 +1206,7 @@ void ModuleMapParser::parseModuleDecl() {
case MMToken::UmbrellaKeyword: {
SourceLocation UmbrellaLoc = consumeToken();
if (Tok.is(MMToken::HeaderKeyword))
- parseHeaderDecl(UmbrellaLoc, SourceLocation());
+ parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
else
parseUmbrellaDirDecl(UmbrellaLoc);
break;
@@ -1209,7 +1215,7 @@ void ModuleMapParser::parseModuleDecl() {
case MMToken::ExcludeKeyword: {
SourceLocation ExcludeLoc = consumeToken();
if (Tok.is(MMToken::HeaderKeyword)) {
- parseHeaderDecl(SourceLocation(), ExcludeLoc);
+ parseHeaderDecl(MMToken::ExcludeKeyword, ExcludeLoc);
} else {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
<< "exclude";
@@ -1217,8 +1223,19 @@ void ModuleMapParser::parseModuleDecl() {
break;
}
+ case MMToken::PrivateKeyword: {
+ SourceLocation PrivateLoc = consumeToken();
+ if (Tok.is(MMToken::HeaderKeyword)) {
+ parseHeaderDecl(MMToken::PrivateKeyword, PrivateLoc);
+ } else {
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
+ << "private";
+ }
+ break;
+ }
+
case MMToken::HeaderKeyword:
- parseHeaderDecl(SourceLocation(), SourceLocation());
+ parseHeaderDecl(MMToken::HeaderKeyword, SourceLocation());
break;
case MMToken::LinkKeyword:
@@ -1314,14 +1331,11 @@ static void appendSubframeworkPaths(Module *Mod,
/// header-declaration:
/// 'umbrella'[opt] 'header' string-literal
/// 'exclude'[opt] 'header' string-literal
-void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
- SourceLocation ExcludeLoc) {
+void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
+ SourceLocation LeadingLoc) {
assert(Tok.is(MMToken::HeaderKeyword));
consumeToken();
- bool Umbrella = UmbrellaLoc.isValid();
- bool Exclude = ExcludeLoc.isValid();
- assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
// Parse the header name.
if (!Tok.is(MMToken::StringLiteral)) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
@@ -1333,7 +1347,7 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
SourceLocation FileNameLoc = consumeToken();
// Check whether we already have an umbrella.
- if (Umbrella && ActiveModule->Umbrella) {
+ if (LeadingToken == MMToken::UmbrellaKeyword && ActiveModule->Umbrella) {
Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
<< ActiveModule->getFullModuleName();
HadError = true;
@@ -1379,8 +1393,9 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
// 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.
- if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
- BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
+ if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword &&
+ BuiltinIncludeDir && BuiltinIncludeDir != Directory &&
+ isBuiltinHeader(FileName)) {
SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
llvm::sys::path::append(BuiltinPathName, FileName);
BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
@@ -1403,10 +1418,10 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
<< FileName << OwningModule.getModule()->getFullModuleName();
HadError = true;
- } else if (Umbrella) {
+ } else if (LeadingToken == MMToken::UmbrellaKeyword) {
const DirectoryEntry *UmbrellaDir = File->getDir();
if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
- Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
+ Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash)
<< UmbrellaModule->getFullModuleName();
HadError = true;
} else {
@@ -1415,17 +1430,25 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
}
} else {
// Record this header.
- Map.addHeader(ActiveModule, File, Exclude);
+ ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
+ if (LeadingToken == MMToken::ExcludeKeyword)
+ Role = ModuleMap::ExcludedHeader;
+ else if (LeadingToken == MMToken::PrivateKeyword)
+ Role = ModuleMap::PrivateHeader;
+ else
+ assert(LeadingToken == MMToken::HeaderKeyword);
+
+ Map.addHeader(ActiveModule, File, Role);
// If there is a builtin counterpart to this file, add it now.
if (BuiltinFile)
- Map.addHeader(ActiveModule, BuiltinFile, Exclude);
+ Map.addHeader(ActiveModule, BuiltinFile, Role);
}
- } else if (!Exclude) {
+ } else if (LeadingToken != MMToken::ExcludeKeyword) {
// Ignore excluded header files. They're optional anyway.
Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
- << Umbrella << FileName;
+ << (LeadingToken == MMToken::UmbrellaKeyword) << FileName;
HadError = true;
}
}
@@ -1792,6 +1815,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
case MMToken::ExplicitKeyword:
case MMToken::ModuleKeyword:
case MMToken::HeaderKeyword:
+ case MMToken::PrivateKeyword:
case MMToken::UmbrellaKeyword:
default:
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
@@ -1918,6 +1942,7 @@ bool ModuleMapParser::parseModuleMapFile() {
case MMToken::LinkKeyword:
case MMToken::LSquare:
case MMToken::Period:
+ case MMToken::PrivateKeyword:
case MMToken::RBrace:
case MMToken::RSquare:
case MMToken::RequiresKeyword:
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index c25e317b42..026a7e7228 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -532,13 +532,14 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() {
}
const FileEntry *Preprocessor::LookupFile(
+ SourceLocation FilenameLoc,
StringRef Filename,
bool isAngled,
const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir,
SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath,
- Module **SuggestedModule,
+ ModuleMap::KnownHeader *SuggestedModule,
bool SkipCache) {
// If the header lookup mechanism may be relative to the current file, pass in
// info about where the current file is.
@@ -564,7 +565,32 @@ const FileEntry *Preprocessor::LookupFile(
const FileEntry *FE = HeaderInfo.LookupFile(
Filename, isAngled, FromDir, CurDir, CurFileEnt,
SearchPath, RelativePath, SuggestedModule, SkipCache);
- if (FE) return FE;
+ if (FE) {
+ if (SuggestedModule) {
+ Module *RequestedModule = SuggestedModule->getModule();
+ if (RequestedModule) {
+ ModuleMap::ModuleHeaderRole Role = SuggestedModule->getRole();
+ #ifndef NDEBUG
+ // Check for consistency between the module header role
+ // as obtained from the lookup and as obtained from the module.
+ // This check is not cheap, so enable it only for debugging.
+ SmallVectorImpl<const FileEntry *> &PvtHdrs
+ = RequestedModule->PrivateHeaders;
+ SmallVectorImpl<const FileEntry *>::iterator Look
+ = std::find(PvtHdrs.begin(), PvtHdrs.end(), FE);
+ bool IsPrivate = Look != PvtHdrs.end();
+ assert((IsPrivate && Role == ModuleMap::PrivateHeader)
+ || (!IsPrivate && Role != ModuleMap::PrivateHeader));
+ #endif
+ if (Role == ModuleMap::PrivateHeader) {
+ if (RequestedModule->getTopLevelModule() != getCurrentModule())
+ Diag(FilenameLoc, diag::error_use_of_private_header_outside_module)
+ << Filename;
+ }
+ }
+ }
+ return FE;
+ }
// Otherwise, see if this is a subframework header. If so, this is relative
// to one of the headers on the #include stack. Walk the list of the current
@@ -1390,9 +1416,10 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
SmallString<1024> RelativePath;
// We get the raw path only if we have 'Callbacks' to which we later pass
// the path.
- Module *SuggestedModule = 0;
+ ModuleMap::KnownHeader SuggestedModule;
+ SourceLocation FilenameLoc = FilenameTok.getLocation();
const FileEntry *File = LookupFile(
- Filename, isAngled, LookupFrom, CurDir,
+ FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL,
getLangOpts().Modules? &SuggestedModule : 0);
@@ -1407,8 +1434,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
HeaderInfo.AddSearchPath(DL, isAngled);
// Try the lookup again, skipping the cache.
- File = LookupFile(Filename, isAngled, LookupFrom, CurDir, 0, 0,
- getLangOpts().Modules? &SuggestedModule : 0,
+ File = LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
+ 0, 0, getLangOpts().Modules? &SuggestedModule : 0,
/*SkipCache*/true);
}
}
@@ -1429,7 +1456,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// brackets, we can attempt a lookup as though it were a quoted path to
// provide the user with a possible fixit.
if (isAngled) {
- File = LookupFile(Filename, false, LookupFrom, CurDir,
+ File = LookupFile(FilenameLoc, Filename, false, LookupFrom, CurDir,
Callbacks ? &SearchPath : 0,
Callbacks ? &RelativePath : 0,
getLangOpts().Modules ? &SuggestedModule : 0);
@@ -1455,7 +1482,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// FIXME: Should we have a second loadModule() overload to avoid this
// extra lookup step?
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
- for (Module *Mod = SuggestedModule; Mod; Mod = Mod->Parent)
+ for (Module *Mod = SuggestedModule.getModule(); Mod; Mod = Mod->Parent)
Path.push_back(std::make_pair(getIdentifierInfo(Mod->Name),
FilenameTok.getLocation()));
std::reverse(Path.begin(), Path.end());
@@ -1514,7 +1541,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
ModuleLoadResult Imported
= TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
/*IsIncludeDirective=*/true);
- assert((Imported == 0 || Imported == SuggestedModule) &&
+ assert((Imported == 0 || Imported == SuggestedModule.getModule()) &&
"the imported module is different than the suggested one");
if (!Imported && hadModuleLoaderFatalFailure()) {
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 3abca1f149..13fdf854fd 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -992,7 +992,8 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
// Search include directories.
const DirectoryLookup *CurDir;
const FileEntry *File =
- PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL, NULL, NULL);
+ PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir, NULL,
+ NULL, NULL);
// Get the result value. A result of true means the file exists.
return File != 0;
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index b2ae4c9c44..4ba461a8a3 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -466,8 +466,8 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
// Search include directories for this file.
const DirectoryLookup *CurDir;
- const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL, NULL,
- NULL);
+ const FileEntry *File = LookupFile(FilenameTok.getLocation(), Filename,
+ isAngled, 0, CurDir, NULL, NULL, NULL);
if (File == 0) {
if (!SuppressIncludeNotFoundError)
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index fd4f90e3ef..f33e0e14cf 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1281,6 +1281,8 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
using namespace clang::io;
HeaderFileInfo HFI;
unsigned Flags = *d++;
+ HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>
+ ((Flags >> 6) & 0x03);
HFI.isImport = (Flags >> 5) & 0x01;
HFI.isPragmaOnce = (Flags >> 4) & 0x01;
HFI.DirInfo = (Flags >> 2) & 0x03;
@@ -1307,7 +1309,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
FileManager &FileMgr = Reader.getFileManager();
ModuleMap &ModMap =
Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
- ModMap.addHeader(Mod, FileMgr.getFile(key.Filename), /*Excluded=*/false);
+ ModMap.addHeader(Mod, FileMgr.getFile(key.Filename), HFI.getHeaderRole());
}
}
@@ -3767,6 +3769,21 @@ bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
break;
}
+ case SUBMODULE_PRIVATE_HEADER: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return true;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ // We lazily associate headers with their modules via the HeaderInfoTable.
+ // FIXME: Re-evaluate this section; maybe only store InputFile IDs instead
+ // of complete filenames or remove it entirely.
+ break;
+ }
+
case SUBMODULE_TOPHEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index ece297f3e5..3654ec27f4 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1476,7 +1476,8 @@ namespace {
using namespace clang::io;
uint64_t Start = Out.tell(); (void)Start;
- unsigned char Flags = (Data.isImport << 5)
+ unsigned char Flags = (Data.HeaderRole << 6)
+ | (Data.isImport << 5)
| (Data.isPragmaOnce << 4)
| (Data.DirInfo << 2)
| (Data.Resolved << 1)
@@ -1507,7 +1508,7 @@ namespace {
Emit32(Out, Offset);
if (Data.isModuleHeader) {
- Module *Mod = HS.findModuleForHeader(key.FE);
+ Module *Mod = HS.findModuleForHeader(key.FE).getModule();
Emit32(Out, Writer.getExistingSubmoduleID(Mod));
}
@@ -2261,6 +2262,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
+ unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ Abbrev = new BitCodeAbbrev();
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
@@ -2333,11 +2339,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
}
// Emit the headers.
- for (unsigned I = 0, N = Mod->Headers.size(); I != N; ++I) {
+ for (unsigned I = 0, N = Mod->NormalHeaders.size(); I != N; ++I) {
Record.clear();
Record.push_back(SUBMODULE_HEADER);
Stream.EmitRecordWithBlob(HeaderAbbrev, Record,
- Mod->Headers[I]->getName());
+ Mod->NormalHeaders[I]->getName());
}
// Emit the excluded headers.
for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) {
@@ -2346,6 +2352,13 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record,
Mod->ExcludedHeaders[I]->getName());
}
+ // Emit the private headers.
+ for (unsigned I = 0, N = Mod->PrivateHeaders.size(); I != N; ++I) {
+ Record.clear();
+ Record.push_back(SUBMODULE_PRIVATE_HEADER);
+ Stream.EmitRecordWithBlob(PrivateHeaderAbbrev, Record,
+ Mod->PrivateHeaders[I]->getName());
+ }
ArrayRef<const FileEntry *>
TopHeaders = Mod->getTopHeaders(PP->getFileManager());
for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) {