mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-26 14:56:10 +00:00
This patch adds new private headers to the module map. Private
headers may be included from within the module, but not from outside the module. llvm-svn: 184471
This commit is contained in:
parent
664c4c678b
commit
b53e5483b0
@ -231,8 +231,8 @@ Module map files use a simplified form of the C99 lexer, with the same rules for
|
|||||||
|
|
||||||
``config_macros`` ``export`` ``module``
|
``config_macros`` ``export`` ``module``
|
||||||
``conflict`` ``framework`` ``requires``
|
``conflict`` ``framework`` ``requires``
|
||||||
``exclude`` ``header`` ``umbrella``
|
``exclude`` ``header`` ``private``
|
||||||
``explicit`` ``link``
|
``explicit`` ``link`` ``umbrella``
|
||||||
|
|
||||||
Module map file
|
Module map file
|
||||||
---------------
|
---------------
|
||||||
@ -360,6 +360,7 @@ A header declaration specifies that a particular header is associated with the e
|
|||||||
|
|
||||||
*header-declaration*:
|
*header-declaration*:
|
||||||
``umbrella``:sub:`opt` ``header`` *string-literal*
|
``umbrella``:sub:`opt` ``header`` *string-literal*
|
||||||
|
``private`` ``header`` *string-literal*
|
||||||
``exclude`` ``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.
|
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
|
``-Wincomplete-umbrella`` warning option to ask Clang to complain
|
||||||
about headers not covered by the umbrella header or the module map.
|
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.
|
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).
|
**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).
|
||||||
|
@ -585,7 +585,9 @@ def warn_forgotten_module_header : Warning<
|
|||||||
InGroup<IncompleteModule>, DefaultIgnore;
|
InGroup<IncompleteModule>, DefaultIgnore;
|
||||||
def err_expected_id_building_module : Error<
|
def err_expected_id_building_module : Error<
|
||||||
"expected a module name in '__building_module' expression">;
|
"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<
|
def warn_header_guard : Warning<
|
||||||
"%0 is used as a header guard here, followed by #define of a different macro">,
|
"%0 is used as a header guard here, followed by #define of a different macro">,
|
||||||
InGroup<DiagGroup<"header-guard">>;
|
InGroup<DiagGroup<"header-guard">>;
|
||||||
|
@ -77,11 +77,14 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
/// \brief The headers that are part of this module.
|
/// \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.
|
/// \brief The headers that are explicitly excluded from this module.
|
||||||
SmallVector<const FileEntry *, 2> ExcludedHeaders;
|
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.
|
/// \brief The set of language features required to use this module.
|
||||||
///
|
///
|
||||||
/// If any of these features is not present, the \c IsAvailable bit
|
/// If any of these features is not present, the \c IsAvailable bit
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "clang/Basic/LLVM.h"
|
#include "clang/Basic/LLVM.h"
|
||||||
#include "clang/Basic/SourceManager.h"
|
#include "clang/Basic/SourceManager.h"
|
||||||
|
#include "clang/Lex/ModuleMap.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class HeaderMap;
|
class HeaderMap;
|
||||||
@ -158,7 +159,7 @@ public:
|
|||||||
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
|
const FileEntry *LookupFile(StringRef Filename, HeaderSearch &HS,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule,
|
ModuleMap::KnownHeader *SuggestedModule,
|
||||||
bool &InUserSpecifiedSystemFramework) const;
|
bool &InUserSpecifiedSystemFramework) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -166,7 +167,7 @@ private:
|
|||||||
StringRef Filename, HeaderSearch &HS,
|
StringRef Filename, HeaderSearch &HS,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule,
|
ModuleMap::KnownHeader *SuggestedModule,
|
||||||
bool &InUserSpecifiedSystemHeader) const;
|
bool &InUserSpecifiedSystemHeader) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -56,6 +56,10 @@ struct HeaderFileInfo {
|
|||||||
|
|
||||||
/// \brief Whether this header is part of the module that we are building.
|
/// \brief Whether this header is part of the module that we are building.
|
||||||
unsigned isCompilingModuleHeader : 1;
|
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
|
/// \brief Whether this structure is considered to already have been
|
||||||
/// "resolved", meaning that it was loaded from the external source.
|
/// "resolved", meaning that it was loaded from the external source.
|
||||||
@ -97,6 +101,7 @@ struct HeaderFileInfo {
|
|||||||
HeaderFileInfo()
|
HeaderFileInfo()
|
||||||
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
|
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
|
||||||
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
|
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
|
||||||
|
HeaderRole(ModuleMap::NormalHeader),
|
||||||
Resolved(false), IndexHeaderMapHeader(false),
|
Resolved(false), IndexHeaderMapHeader(false),
|
||||||
NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {}
|
NumIncludes(0), ControllingMacroID(0), ControllingMacro(0) {}
|
||||||
|
|
||||||
@ -110,6 +115,16 @@ struct HeaderFileInfo {
|
|||||||
return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
|
return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
|
||||||
ControllingMacroID;
|
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
|
/// \brief An external source of header file information, which may supply
|
||||||
@ -357,7 +372,7 @@ public:
|
|||||||
const FileEntry *CurFileEnt,
|
const FileEntry *CurFileEnt,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule,
|
ModuleMap::KnownHeader *SuggestedModule,
|
||||||
bool SkipCache = false);
|
bool SkipCache = false);
|
||||||
|
|
||||||
/// \brief Look up a subframework for the specified \#include file.
|
/// \brief Look up a subframework for the specified \#include file.
|
||||||
@ -371,7 +386,7 @@ public:
|
|||||||
const FileEntry *RelativeFileEnt,
|
const FileEntry *RelativeFileEnt,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule);
|
ModuleMap::KnownHeader *SuggestedModule);
|
||||||
|
|
||||||
/// \brief Look up the specified framework name in our framework cache.
|
/// \brief Look up the specified framework name in our framework cache.
|
||||||
/// \returns The DirectoryEntry it is in if we know, null otherwise.
|
/// \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.
|
/// \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
|
/// \brief Increment the count for the number of times the specified
|
||||||
/// FileEntry has been entered.
|
/// FileEntry has been entered.
|
||||||
@ -484,7 +501,7 @@ public:
|
|||||||
/// \brief Retrieve the module that corresponds to the given file, if any.
|
/// \brief Retrieve the module that corresponds to the given file, if any.
|
||||||
///
|
///
|
||||||
/// \param File The header that we wish to map to a module.
|
/// \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.
|
/// \brief Read the contents of the given module map file.
|
||||||
///
|
///
|
||||||
|
@ -58,24 +58,40 @@ class ModuleMap {
|
|||||||
/// \brief The top-level modules that are known.
|
/// \brief The top-level modules that are known.
|
||||||
llvm::StringMap<Module *> Modules;
|
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,
|
/// \brief A header that is known to reside within a given module,
|
||||||
/// whether it was included or excluded.
|
/// whether it was included or excluded.
|
||||||
class KnownHeader {
|
class KnownHeader {
|
||||||
llvm::PointerIntPair<Module *, 1, bool> Storage;
|
llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
KnownHeader() : Storage(0, false) { }
|
KnownHeader() : Storage(0, NormalHeader) { }
|
||||||
KnownHeader(Module *M, bool Excluded) : Storage(M, Excluded) { }
|
KnownHeader(Module *M, ModuleHeaderRole Role) : Storage(M, Role) { }
|
||||||
|
|
||||||
/// \brief Retrieve the module the header is stored in.
|
/// \brief Retrieve the module the header is stored in.
|
||||||
Module *getModule() const { return Storage.getPointer(); }
|
Module *getModule() const { return Storage.getPointer(); }
|
||||||
|
|
||||||
/// \brief Whether this header is explicitly excluded from the module.
|
/// \brief The role of this header within the module.
|
||||||
bool isExcluded() const { return Storage.getInt(); }
|
ModuleHeaderRole getRole() const { return Storage.getInt(); }
|
||||||
|
|
||||||
/// \brief Whether this header is available in the module.
|
/// \brief Whether this header is available in the module.
|
||||||
bool isAvailable() const {
|
bool isAvailable() const {
|
||||||
return !isExcluded() && getModule()->isAvailable();
|
return getRole() != ExcludedHeader && getModule()->isAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// \brief Whether this known header is valid (i.e., it has an
|
// \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; }
|
LLVM_EXPLICIT operator bool() const { return Storage.getPointer() != 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap;
|
typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap;
|
||||||
|
|
||||||
/// \brief Mapping from each header to the module that owns the contents of
|
/// \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.
|
/// \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.
|
/// 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
|
/// \brief Determine whether the given header is part of a module
|
||||||
/// marked 'unavailable'.
|
/// marked 'unavailable'.
|
||||||
@ -310,9 +328,9 @@ public:
|
|||||||
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir);
|
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir);
|
||||||
|
|
||||||
/// \brief Adds this header to the given module.
|
/// \brief Adds this header to the given module.
|
||||||
/// \param Excluded Whether this header is explicitly excluded from the
|
/// \param Role The role of the header wrt the module.
|
||||||
/// module; otherwise, it's included in the module.
|
void addHeader(Module *Mod, const FileEntry *Header,
|
||||||
void addHeader(Module *Mod, const FileEntry *Header, bool Excluded);
|
ModuleHeaderRole Role);
|
||||||
|
|
||||||
/// \brief Parse the given module map file, and record any modules we
|
/// \brief Parse the given module map file, and record any modules we
|
||||||
/// encounter.
|
/// encounter.
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "clang/Basic/SourceLocation.h"
|
#include "clang/Basic/SourceLocation.h"
|
||||||
#include "clang/Lex/Lexer.h"
|
#include "clang/Lex/Lexer.h"
|
||||||
#include "clang/Lex/MacroInfo.h"
|
#include "clang/Lex/MacroInfo.h"
|
||||||
|
#include "clang/Lex/ModuleMap.h"
|
||||||
#include "clang/Lex/PPCallbacks.h"
|
#include "clang/Lex/PPCallbacks.h"
|
||||||
#include "clang/Lex/PTHLexer.h"
|
#include "clang/Lex/PTHLexer.h"
|
||||||
#include "clang/Lex/PTHManager.h"
|
#include "clang/Lex/PTHManager.h"
|
||||||
@ -1227,12 +1228,12 @@ public:
|
|||||||
///
|
///
|
||||||
/// Returns null on failure. \p isAngled indicates whether the file
|
/// Returns null on failure. \p isAngled indicates whether the file
|
||||||
/// reference is for system \#include's or not (i.e. using <> instead of "").
|
/// 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,
|
bool isAngled, const DirectoryLookup *FromDir,
|
||||||
const DirectoryLookup *&CurDir,
|
const DirectoryLookup *&CurDir,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule,
|
ModuleMap::KnownHeader *SuggestedModule,
|
||||||
bool SkipCache = false);
|
bool SkipCache = false);
|
||||||
|
|
||||||
/// GetCurLookup - The DirectoryLookup structure used to find the current
|
/// GetCurLookup - The DirectoryLookup structure used to find the current
|
||||||
|
@ -623,7 +623,9 @@ namespace clang {
|
|||||||
/// \brief Specifies a configuration macro for this module.
|
/// \brief Specifies a configuration macro for this module.
|
||||||
SUBMODULE_CONFIG_MACRO = 11,
|
SUBMODULE_CONFIG_MACRO = 11,
|
||||||
/// \brief Specifies a conflict with another module.
|
/// \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.
|
/// \brief Record types used within a comments block.
|
||||||
|
@ -293,10 +293,10 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
|
|||||||
OS << "\n";
|
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.indent(Indent + 2);
|
||||||
OS << "header \"";
|
OS << "header \"";
|
||||||
OS.write_escaped(Headers[I]->getName());
|
OS.write_escaped(NormalHeaders[I]->getName());
|
||||||
OS << "\"\n";
|
OS << "\"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,6 +306,13 @@ void Module::print(raw_ostream &OS, unsigned Indent) const {
|
|||||||
OS.write_escaped(ExcludedHeaders[I]->getName());
|
OS.write_escaped(ExcludedHeaders[I]->getName());
|
||||||
OS << "\"\n";
|
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();
|
for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end();
|
||||||
MI != MIEnd; ++MI)
|
MI != MIEnd; ++MI)
|
||||||
|
@ -172,11 +172,12 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Add includes for each of these headers.
|
// Add includes for each of these headers.
|
||||||
for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) {
|
for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) {
|
||||||
const FileEntry *Header = Module->Headers[I];
|
const FileEntry *Header = Module->NormalHeaders[I];
|
||||||
Module->addTopHeader(Header);
|
Module->addTopHeader(Header);
|
||||||
addHeaderInclude(Header, Includes, LangOpts);
|
addHeaderInclude(Header, Includes, LangOpts);
|
||||||
}
|
}
|
||||||
|
// Note that Module->PrivateHeaders will not be a TopHeader.
|
||||||
|
|
||||||
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
|
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
|
||||||
Module->addTopHeader(UmbrellaHeader);
|
Module->addTopHeader(UmbrellaHeader);
|
||||||
|
@ -371,7 +371,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
|
|||||||
|
|
||||||
// Lookup file via Preprocessor, like a #include.
|
// Lookup file via Preprocessor, like a #include.
|
||||||
const DirectoryLookup *CurDir;
|
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);
|
NULL, NULL, 0);
|
||||||
if (!FE) {
|
if (!FE) {
|
||||||
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
|
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
|
||||||
|
@ -223,7 +223,7 @@ const FileEntry *DirectoryLookup::LookupFile(
|
|||||||
HeaderSearch &HS,
|
HeaderSearch &HS,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule,
|
ModuleMap::KnownHeader *SuggestedModule,
|
||||||
bool &InUserSpecifiedSystemFramework) const {
|
bool &InUserSpecifiedSystemFramework) const {
|
||||||
InUserSpecifiedSystemFramework = false;
|
InUserSpecifiedSystemFramework = false;
|
||||||
|
|
||||||
@ -337,7 +337,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
|
|||||||
HeaderSearch &HS,
|
HeaderSearch &HS,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule,
|
ModuleMap::KnownHeader *SuggestedModule,
|
||||||
bool &InUserSpecifiedSystemFramework) const
|
bool &InUserSpecifiedSystemFramework) const
|
||||||
{
|
{
|
||||||
FileManager &FileMgr = HS.getFileMgr();
|
FileManager &FileMgr = HS.getFileMgr();
|
||||||
@ -496,11 +496,11 @@ const FileEntry *HeaderSearch::LookupFile(
|
|||||||
const FileEntry *CurFileEnt,
|
const FileEntry *CurFileEnt,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule,
|
ModuleMap::KnownHeader *SuggestedModule,
|
||||||
bool SkipCache)
|
bool SkipCache)
|
||||||
{
|
{
|
||||||
if (SuggestedModule)
|
if (SuggestedModule)
|
||||||
*SuggestedModule = 0;
|
*SuggestedModule = ModuleMap::KnownHeader();
|
||||||
|
|
||||||
// If 'Filename' is absolute, check to see if it exists and no searching.
|
// If 'Filename' is absolute, check to see if it exists and no searching.
|
||||||
if (llvm::sys::path::is_absolute(Filename)) {
|
if (llvm::sys::path::is_absolute(Filename)) {
|
||||||
@ -676,7 +676,7 @@ LookupSubframeworkHeader(StringRef Filename,
|
|||||||
const FileEntry *ContextFileEnt,
|
const FileEntry *ContextFileEnt,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule) {
|
ModuleMap::KnownHeader *SuggestedModule) {
|
||||||
assert(ContextFileEnt && "No context file?");
|
assert(ContextFileEnt && "No context file?");
|
||||||
|
|
||||||
// Framework names must have a '/' in the filename. Find it.
|
// 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,
|
void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
|
||||||
|
ModuleMap::ModuleHeaderRole Role,
|
||||||
bool isCompilingModuleHeader) {
|
bool isCompilingModuleHeader) {
|
||||||
if (FE->getUID() >= FileInfo.size())
|
if (FE->getUID() >= FileInfo.size())
|
||||||
FileInfo.resize(FE->getUID()+1);
|
FileInfo.resize(FE->getUID()+1);
|
||||||
@ -874,6 +875,7 @@ void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE,
|
|||||||
HeaderFileInfo &HFI = FileInfo[FE->getUID()];
|
HeaderFileInfo &HFI = FileInfo[FE->getUID()];
|
||||||
HFI.isModuleHeader = true;
|
HFI.isModuleHeader = true;
|
||||||
HFI.isCompilingModuleHeader = isCompilingModuleHeader;
|
HFI.isCompilingModuleHeader = isCompilingModuleHeader;
|
||||||
|
HFI.setHeaderRole(Role);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
|
bool HeaderSearch::ShouldEnterIncludeFile(const FileEntry *File, bool isImport){
|
||||||
@ -966,16 +968,14 @@ bool HeaderSearch::hasModuleMap(StringRef FileName,
|
|||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Module *HeaderSearch::findModuleForHeader(const FileEntry *File) const {
|
ModuleMap::KnownHeader
|
||||||
|
HeaderSearch::findModuleForHeader(const FileEntry *File) const {
|
||||||
if (ExternalSource) {
|
if (ExternalSource) {
|
||||||
// Make sure the external source has handled header info about this file,
|
// Make sure the external source has handled header info about this file,
|
||||||
// which includes whether the file is part of a module.
|
// which includes whether the file is part of a module.
|
||||||
(void)getFileInfo(File);
|
(void)getFileInfo(File);
|
||||||
}
|
}
|
||||||
if (Module *Mod = ModMap.findModuleForHeader(File))
|
return ModMap.findModuleForHeader(File);
|
||||||
return Mod;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HeaderSearch::loadModuleMapFile(const FileEntry *File) {
|
bool HeaderSearch::loadModuleMapFile(const FileEntry *File) {
|
||||||
|
@ -168,14 +168,14 @@ static bool isBuiltinHeader(StringRef FileName) {
|
|||||||
.Default(false);
|
.Default(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
|
ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
|
||||||
HeadersMap::iterator Known = Headers.find(File);
|
HeadersMap::iterator Known = Headers.find(File);
|
||||||
if (Known != Headers.end()) {
|
if (Known != Headers.end()) {
|
||||||
// If a header is not available, don't report that it maps to anything.
|
// If a header is not available, don't report that it maps to anything.
|
||||||
if (!Known->second.isAvailable())
|
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,
|
// 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 (Known != Headers.end()) {
|
||||||
// If a header is not available, don't report that it maps to anything.
|
// If a header is not available, don't report that it maps to anything.
|
||||||
if (!Known->second.isAvailable())
|
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;
|
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
|
// If a header corresponds to an unavailable module, don't report
|
||||||
// that it maps to anything.
|
// that it maps to anything.
|
||||||
if (!Result->isAvailable())
|
if (!Result->isAvailable())
|
||||||
return 0;
|
return KnownHeader();
|
||||||
|
|
||||||
return Result;
|
return Headers[File];
|
||||||
}
|
}
|
||||||
|
|
||||||
SkippedDirs.push_back(Dir);
|
SkippedDirs.push_back(Dir);
|
||||||
@ -283,7 +283,7 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
|
|||||||
Dir = SourceMgr->getFileManager().getDirectory(DirName);
|
Dir = SourceMgr->getFileManager().getDirectory(DirName);
|
||||||
} while (Dir);
|
} while (Dir);
|
||||||
|
|
||||||
return 0;
|
return KnownHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
|
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
|
||||||
@ -527,7 +527,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
|
|||||||
|
|
||||||
// umbrella header "umbrella-header-name"
|
// umbrella header "umbrella-header-name"
|
||||||
Result->Umbrella = UmbrellaHeader;
|
Result->Umbrella = UmbrellaHeader;
|
||||||
Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
|
Headers[UmbrellaHeader] = KnownHeader(Result, NormalHeader);
|
||||||
UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
|
UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
|
||||||
|
|
||||||
// export *
|
// export *
|
||||||
@ -593,7 +593,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
|
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
|
||||||
Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
|
Headers[UmbrellaHeader] = KnownHeader(Mod, NormalHeader);
|
||||||
Mod->Umbrella = UmbrellaHeader;
|
Mod->Umbrella = UmbrellaHeader;
|
||||||
UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
|
UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
|
||||||
}
|
}
|
||||||
@ -604,15 +604,18 @@ void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
|
void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
|
||||||
bool Excluded) {
|
ModuleHeaderRole Role) {
|
||||||
if (Excluded) {
|
if (Role == ExcludedHeader) {
|
||||||
Mod->ExcludedHeaders.push_back(Header);
|
Mod->ExcludedHeaders.push_back(Header);
|
||||||
} else {
|
} 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;
|
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 *
|
const FileEntry *
|
||||||
@ -688,7 +691,7 @@ Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
|
|||||||
while (const FileEntry *ExpansionFile
|
while (const FileEntry *ExpansionFile
|
||||||
= SrcMgr.getFileEntryForID(ExpansionFileID)) {
|
= SrcMgr.getFileEntryForID(ExpansionFileID)) {
|
||||||
// Find the module that owns this header (if any).
|
// Find the module that owns this header (if any).
|
||||||
if (Module *Mod = findModuleForHeader(ExpansionFile))
|
if (Module *Mod = findModuleForHeader(ExpansionFile).getModule())
|
||||||
return Mod;
|
return Mod;
|
||||||
|
|
||||||
// No module owns this header, so look up the inclusion chain to see if
|
// No module owns this header, so look up the inclusion chain to see if
|
||||||
@ -724,6 +727,7 @@ namespace clang {
|
|||||||
LinkKeyword,
|
LinkKeyword,
|
||||||
ModuleKeyword,
|
ModuleKeyword,
|
||||||
Period,
|
Period,
|
||||||
|
PrivateKeyword,
|
||||||
UmbrellaKeyword,
|
UmbrellaKeyword,
|
||||||
RequiresKeyword,
|
RequiresKeyword,
|
||||||
Star,
|
Star,
|
||||||
@ -809,7 +813,8 @@ namespace clang {
|
|||||||
bool parseModuleId(ModuleId &Id);
|
bool parseModuleId(ModuleId &Id);
|
||||||
void parseModuleDecl();
|
void parseModuleDecl();
|
||||||
void parseRequiresDecl();
|
void parseRequiresDecl();
|
||||||
void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
|
void parseHeaderDecl(clang::MMToken::TokenKind,
|
||||||
|
SourceLocation LeadingLoc);
|
||||||
void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
|
void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
|
||||||
void parseExportDecl();
|
void parseExportDecl();
|
||||||
void parseLinkDecl();
|
void parseLinkDecl();
|
||||||
@ -861,6 +866,7 @@ retry:
|
|||||||
.Case("header", MMToken::HeaderKeyword)
|
.Case("header", MMToken::HeaderKeyword)
|
||||||
.Case("link", MMToken::LinkKeyword)
|
.Case("link", MMToken::LinkKeyword)
|
||||||
.Case("module", MMToken::ModuleKeyword)
|
.Case("module", MMToken::ModuleKeyword)
|
||||||
|
.Case("private", MMToken::PrivateKeyword)
|
||||||
.Case("requires", MMToken::RequiresKeyword)
|
.Case("requires", MMToken::RequiresKeyword)
|
||||||
.Case("umbrella", MMToken::UmbrellaKeyword)
|
.Case("umbrella", MMToken::UmbrellaKeyword)
|
||||||
.Default(MMToken::Identifier);
|
.Default(MMToken::Identifier);
|
||||||
@ -1200,7 +1206,7 @@ void ModuleMapParser::parseModuleDecl() {
|
|||||||
case MMToken::UmbrellaKeyword: {
|
case MMToken::UmbrellaKeyword: {
|
||||||
SourceLocation UmbrellaLoc = consumeToken();
|
SourceLocation UmbrellaLoc = consumeToken();
|
||||||
if (Tok.is(MMToken::HeaderKeyword))
|
if (Tok.is(MMToken::HeaderKeyword))
|
||||||
parseHeaderDecl(UmbrellaLoc, SourceLocation());
|
parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
|
||||||
else
|
else
|
||||||
parseUmbrellaDirDecl(UmbrellaLoc);
|
parseUmbrellaDirDecl(UmbrellaLoc);
|
||||||
break;
|
break;
|
||||||
@ -1209,7 +1215,7 @@ void ModuleMapParser::parseModuleDecl() {
|
|||||||
case MMToken::ExcludeKeyword: {
|
case MMToken::ExcludeKeyword: {
|
||||||
SourceLocation ExcludeLoc = consumeToken();
|
SourceLocation ExcludeLoc = consumeToken();
|
||||||
if (Tok.is(MMToken::HeaderKeyword)) {
|
if (Tok.is(MMToken::HeaderKeyword)) {
|
||||||
parseHeaderDecl(SourceLocation(), ExcludeLoc);
|
parseHeaderDecl(MMToken::ExcludeKeyword, ExcludeLoc);
|
||||||
} else {
|
} else {
|
||||||
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
|
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
|
||||||
<< "exclude";
|
<< "exclude";
|
||||||
@ -1217,8 +1223,19 @@ void ModuleMapParser::parseModuleDecl() {
|
|||||||
break;
|
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:
|
case MMToken::HeaderKeyword:
|
||||||
parseHeaderDecl(SourceLocation(), SourceLocation());
|
parseHeaderDecl(MMToken::HeaderKeyword, SourceLocation());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MMToken::LinkKeyword:
|
case MMToken::LinkKeyword:
|
||||||
@ -1314,14 +1331,11 @@ static void appendSubframeworkPaths(Module *Mod,
|
|||||||
/// header-declaration:
|
/// header-declaration:
|
||||||
/// 'umbrella'[opt] 'header' string-literal
|
/// 'umbrella'[opt] 'header' string-literal
|
||||||
/// 'exclude'[opt] 'header' string-literal
|
/// 'exclude'[opt] 'header' string-literal
|
||||||
void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
|
void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
|
||||||
SourceLocation ExcludeLoc) {
|
SourceLocation LeadingLoc) {
|
||||||
assert(Tok.is(MMToken::HeaderKeyword));
|
assert(Tok.is(MMToken::HeaderKeyword));
|
||||||
consumeToken();
|
consumeToken();
|
||||||
|
|
||||||
bool Umbrella = UmbrellaLoc.isValid();
|
|
||||||
bool Exclude = ExcludeLoc.isValid();
|
|
||||||
assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
|
|
||||||
// Parse the header name.
|
// Parse the header name.
|
||||||
if (!Tok.is(MMToken::StringLiteral)) {
|
if (!Tok.is(MMToken::StringLiteral)) {
|
||||||
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
|
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
|
||||||
@ -1333,7 +1347,7 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
|
|||||||
SourceLocation FileNameLoc = consumeToken();
|
SourceLocation FileNameLoc = consumeToken();
|
||||||
|
|
||||||
// Check whether we already have an umbrella.
|
// 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)
|
Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
|
||||||
<< ActiveModule->getFullModuleName();
|
<< ActiveModule->getFullModuleName();
|
||||||
HadError = true;
|
HadError = true;
|
||||||
@ -1379,8 +1393,9 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
|
|||||||
// If this is a system module with a top-level header, this header
|
// If this is a system module with a top-level header, this header
|
||||||
// may have a counterpart (or replacement) in the set of headers
|
// may have a counterpart (or replacement) in the set of headers
|
||||||
// supplied by Clang. Find that builtin header.
|
// supplied by Clang. Find that builtin header.
|
||||||
if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir &&
|
if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword &&
|
||||||
BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) {
|
BuiltinIncludeDir && BuiltinIncludeDir != Directory &&
|
||||||
|
isBuiltinHeader(FileName)) {
|
||||||
SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
|
SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
|
||||||
llvm::sys::path::append(BuiltinPathName, FileName);
|
llvm::sys::path::append(BuiltinPathName, FileName);
|
||||||
BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
|
BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
|
||||||
@ -1403,10 +1418,10 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
|
|||||||
Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
|
Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
|
||||||
<< FileName << OwningModule.getModule()->getFullModuleName();
|
<< FileName << OwningModule.getModule()->getFullModuleName();
|
||||||
HadError = true;
|
HadError = true;
|
||||||
} else if (Umbrella) {
|
} else if (LeadingToken == MMToken::UmbrellaKeyword) {
|
||||||
const DirectoryEntry *UmbrellaDir = File->getDir();
|
const DirectoryEntry *UmbrellaDir = File->getDir();
|
||||||
if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
|
if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
|
||||||
Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
|
Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash)
|
||||||
<< UmbrellaModule->getFullModuleName();
|
<< UmbrellaModule->getFullModuleName();
|
||||||
HadError = true;
|
HadError = true;
|
||||||
} else {
|
} else {
|
||||||
@ -1415,17 +1430,25 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Record this header.
|
// 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 there is a builtin counterpart to this file, add it now.
|
||||||
if (BuiltinFile)
|
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.
|
// Ignore excluded header files. They're optional anyway.
|
||||||
|
|
||||||
Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
|
Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
|
||||||
<< Umbrella << FileName;
|
<< (LeadingToken == MMToken::UmbrellaKeyword) << FileName;
|
||||||
HadError = true;
|
HadError = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1792,6 +1815,7 @@ void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
|
|||||||
case MMToken::ExplicitKeyword:
|
case MMToken::ExplicitKeyword:
|
||||||
case MMToken::ModuleKeyword:
|
case MMToken::ModuleKeyword:
|
||||||
case MMToken::HeaderKeyword:
|
case MMToken::HeaderKeyword:
|
||||||
|
case MMToken::PrivateKeyword:
|
||||||
case MMToken::UmbrellaKeyword:
|
case MMToken::UmbrellaKeyword:
|
||||||
default:
|
default:
|
||||||
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
|
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
|
||||||
@ -1918,6 +1942,7 @@ bool ModuleMapParser::parseModuleMapFile() {
|
|||||||
case MMToken::LinkKeyword:
|
case MMToken::LinkKeyword:
|
||||||
case MMToken::LSquare:
|
case MMToken::LSquare:
|
||||||
case MMToken::Period:
|
case MMToken::Period:
|
||||||
|
case MMToken::PrivateKeyword:
|
||||||
case MMToken::RBrace:
|
case MMToken::RBrace:
|
||||||
case MMToken::RSquare:
|
case MMToken::RSquare:
|
||||||
case MMToken::RequiresKeyword:
|
case MMToken::RequiresKeyword:
|
||||||
|
@ -532,13 +532,14 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const FileEntry *Preprocessor::LookupFile(
|
const FileEntry *Preprocessor::LookupFile(
|
||||||
|
SourceLocation FilenameLoc,
|
||||||
StringRef Filename,
|
StringRef Filename,
|
||||||
bool isAngled,
|
bool isAngled,
|
||||||
const DirectoryLookup *FromDir,
|
const DirectoryLookup *FromDir,
|
||||||
const DirectoryLookup *&CurDir,
|
const DirectoryLookup *&CurDir,
|
||||||
SmallVectorImpl<char> *SearchPath,
|
SmallVectorImpl<char> *SearchPath,
|
||||||
SmallVectorImpl<char> *RelativePath,
|
SmallVectorImpl<char> *RelativePath,
|
||||||
Module **SuggestedModule,
|
ModuleMap::KnownHeader *SuggestedModule,
|
||||||
bool SkipCache) {
|
bool SkipCache) {
|
||||||
// If the header lookup mechanism may be relative to the current file, pass in
|
// If the header lookup mechanism may be relative to the current file, pass in
|
||||||
// info about where the current file is.
|
// info about where the current file is.
|
||||||
@ -564,7 +565,32 @@ const FileEntry *Preprocessor::LookupFile(
|
|||||||
const FileEntry *FE = HeaderInfo.LookupFile(
|
const FileEntry *FE = HeaderInfo.LookupFile(
|
||||||
Filename, isAngled, FromDir, CurDir, CurFileEnt,
|
Filename, isAngled, FromDir, CurDir, CurFileEnt,
|
||||||
SearchPath, RelativePath, SuggestedModule, SkipCache);
|
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
|
// 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
|
// 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;
|
SmallString<1024> RelativePath;
|
||||||
// We get the raw path only if we have 'Callbacks' to which we later pass
|
// We get the raw path only if we have 'Callbacks' to which we later pass
|
||||||
// the path.
|
// the path.
|
||||||
Module *SuggestedModule = 0;
|
ModuleMap::KnownHeader SuggestedModule;
|
||||||
|
SourceLocation FilenameLoc = FilenameTok.getLocation();
|
||||||
const FileEntry *File = LookupFile(
|
const FileEntry *File = LookupFile(
|
||||||
Filename, isAngled, LookupFrom, CurDir,
|
FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
|
||||||
Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL,
|
Callbacks ? &SearchPath : NULL, Callbacks ? &RelativePath : NULL,
|
||||||
getLangOpts().Modules? &SuggestedModule : 0);
|
getLangOpts().Modules? &SuggestedModule : 0);
|
||||||
|
|
||||||
@ -1407,8 +1434,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
|||||||
HeaderInfo.AddSearchPath(DL, isAngled);
|
HeaderInfo.AddSearchPath(DL, isAngled);
|
||||||
|
|
||||||
// Try the lookup again, skipping the cache.
|
// Try the lookup again, skipping the cache.
|
||||||
File = LookupFile(Filename, isAngled, LookupFrom, CurDir, 0, 0,
|
File = LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, CurDir,
|
||||||
getLangOpts().Modules? &SuggestedModule : 0,
|
0, 0, getLangOpts().Modules? &SuggestedModule : 0,
|
||||||
/*SkipCache*/true);
|
/*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
|
// brackets, we can attempt a lookup as though it were a quoted path to
|
||||||
// provide the user with a possible fixit.
|
// provide the user with a possible fixit.
|
||||||
if (isAngled) {
|
if (isAngled) {
|
||||||
File = LookupFile(Filename, false, LookupFrom, CurDir,
|
File = LookupFile(FilenameLoc, Filename, false, LookupFrom, CurDir,
|
||||||
Callbacks ? &SearchPath : 0,
|
Callbacks ? &SearchPath : 0,
|
||||||
Callbacks ? &RelativePath : 0,
|
Callbacks ? &RelativePath : 0,
|
||||||
getLangOpts().Modules ? &SuggestedModule : 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
|
// FIXME: Should we have a second loadModule() overload to avoid this
|
||||||
// extra lookup step?
|
// extra lookup step?
|
||||||
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
|
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),
|
Path.push_back(std::make_pair(getIdentifierInfo(Mod->Name),
|
||||||
FilenameTok.getLocation()));
|
FilenameTok.getLocation()));
|
||||||
std::reverse(Path.begin(), Path.end());
|
std::reverse(Path.begin(), Path.end());
|
||||||
@ -1514,7 +1541,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
|
|||||||
ModuleLoadResult Imported
|
ModuleLoadResult Imported
|
||||||
= TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
|
= TheModuleLoader.loadModule(IncludeTok.getLocation(), Path, Visibility,
|
||||||
/*IsIncludeDirective=*/true);
|
/*IsIncludeDirective=*/true);
|
||||||
assert((Imported == 0 || Imported == SuggestedModule) &&
|
assert((Imported == 0 || Imported == SuggestedModule.getModule()) &&
|
||||||
"the imported module is different than the suggested one");
|
"the imported module is different than the suggested one");
|
||||||
|
|
||||||
if (!Imported && hadModuleLoaderFatalFailure()) {
|
if (!Imported && hadModuleLoaderFatalFailure()) {
|
||||||
|
@ -992,7 +992,8 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
|
|||||||
// Search include directories.
|
// Search include directories.
|
||||||
const DirectoryLookup *CurDir;
|
const DirectoryLookup *CurDir;
|
||||||
const FileEntry *File =
|
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.
|
// Get the result value. A result of true means the file exists.
|
||||||
return File != 0;
|
return File != 0;
|
||||||
|
@ -466,8 +466,8 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
|
|||||||
|
|
||||||
// Search include directories for this file.
|
// Search include directories for this file.
|
||||||
const DirectoryLookup *CurDir;
|
const DirectoryLookup *CurDir;
|
||||||
const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir, NULL, NULL,
|
const FileEntry *File = LookupFile(FilenameTok.getLocation(), Filename,
|
||||||
NULL);
|
isAngled, 0, CurDir, NULL, NULL, NULL);
|
||||||
if (File == 0) {
|
if (File == 0) {
|
||||||
if (!SuppressIncludeNotFoundError)
|
if (!SuppressIncludeNotFoundError)
|
||||||
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
|
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;
|
||||||
|
@ -1281,6 +1281,8 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
|
|||||||
using namespace clang::io;
|
using namespace clang::io;
|
||||||
HeaderFileInfo HFI;
|
HeaderFileInfo HFI;
|
||||||
unsigned Flags = *d++;
|
unsigned Flags = *d++;
|
||||||
|
HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>
|
||||||
|
((Flags >> 6) & 0x03);
|
||||||
HFI.isImport = (Flags >> 5) & 0x01;
|
HFI.isImport = (Flags >> 5) & 0x01;
|
||||||
HFI.isPragmaOnce = (Flags >> 4) & 0x01;
|
HFI.isPragmaOnce = (Flags >> 4) & 0x01;
|
||||||
HFI.DirInfo = (Flags >> 2) & 0x03;
|
HFI.DirInfo = (Flags >> 2) & 0x03;
|
||||||
@ -1307,7 +1309,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
|
|||||||
FileManager &FileMgr = Reader.getFileManager();
|
FileManager &FileMgr = Reader.getFileManager();
|
||||||
ModuleMap &ModMap =
|
ModuleMap &ModMap =
|
||||||
Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
|
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;
|
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: {
|
case SUBMODULE_TOPHEADER: {
|
||||||
if (First) {
|
if (First) {
|
||||||
Error("missing submodule metadata record at beginning of block");
|
Error("missing submodule metadata record at beginning of block");
|
||||||
|
@ -1476,7 +1476,8 @@ namespace {
|
|||||||
using namespace clang::io;
|
using namespace clang::io;
|
||||||
uint64_t Start = Out.tell(); (void)Start;
|
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.isPragmaOnce << 4)
|
||||||
| (Data.DirInfo << 2)
|
| (Data.DirInfo << 2)
|
||||||
| (Data.Resolved << 1)
|
| (Data.Resolved << 1)
|
||||||
@ -1507,7 +1508,7 @@ namespace {
|
|||||||
Emit32(Out, Offset);
|
Emit32(Out, Offset);
|
||||||
|
|
||||||
if (Data.isModuleHeader) {
|
if (Data.isModuleHeader) {
|
||||||
Module *Mod = HS.findModuleForHeader(key.FE);
|
Module *Mod = HS.findModuleForHeader(key.FE).getModule();
|
||||||
Emit32(Out, Writer.getExistingSubmoduleID(Mod));
|
Emit32(Out, Writer.getExistingSubmoduleID(Mod));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2260,6 +2261,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
|
||||||
unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
|
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 = new BitCodeAbbrev();
|
||||||
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));
|
Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
|
||||||
@ -2333,11 +2339,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emit the headers.
|
// 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.clear();
|
||||||
Record.push_back(SUBMODULE_HEADER);
|
Record.push_back(SUBMODULE_HEADER);
|
||||||
Stream.EmitRecordWithBlob(HeaderAbbrev, Record,
|
Stream.EmitRecordWithBlob(HeaderAbbrev, Record,
|
||||||
Mod->Headers[I]->getName());
|
Mod->NormalHeaders[I]->getName());
|
||||||
}
|
}
|
||||||
// Emit the excluded headers.
|
// Emit the excluded headers.
|
||||||
for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) {
|
for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) {
|
||||||
@ -2346,6 +2352,13 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||||||
Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record,
|
Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record,
|
||||||
Mod->ExcludedHeaders[I]->getName());
|
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 *>
|
ArrayRef<const FileEntry *>
|
||||||
TopHeaders = Mod->getTopHeaders(PP->getFileManager());
|
TopHeaders = Mod->getTopHeaders(PP->getFileManager());
|
||||||
for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) {
|
for (unsigned I = 0, N = TopHeaders.size(); I != N; ++I) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user