Introduce module attributes into the module map grammar, along with a
single attribute ("system") that allows us to mark a module as being a "system" module. Each of the headers that makes up a system module is considered to be a system header, so that we (for example) suppress warnings there. If a module is being inferred for a framework, and that framework directory is within a system frameworks directory, infer it as a system framework. llvm-svn: 149143
This commit is contained in:
parent
63fe5697f4
commit
a686e1b05d
|
@ -391,6 +391,8 @@ def err_mmap_expected_module_name : Error<"expected module name">;
|
||||||
def err_mmap_expected_lbrace : Error<"expected '{' to start module '%0'">;
|
def err_mmap_expected_lbrace : Error<"expected '{' to start module '%0'">;
|
||||||
def err_mmap_expected_rbrace : Error<"expected '}'">;
|
def err_mmap_expected_rbrace : Error<"expected '}'">;
|
||||||
def note_mmap_lbrace_match : Note<"to match this '{'">;
|
def note_mmap_lbrace_match : Note<"to match this '{'">;
|
||||||
|
def err_mmap_expected_rsquare : Error<"expected ']' to close attribute">;
|
||||||
|
def note_mmap_lsquare_match : Note<"to match this ']'">;
|
||||||
def err_mmap_expected_member : Error<
|
def err_mmap_expected_member : Error<
|
||||||
"expected umbrella, header, submodule, or module export">;
|
"expected umbrella, header, submodule, or module export">;
|
||||||
def err_mmap_expected_header : Error<"expected a header name after '%0'">;
|
def err_mmap_expected_header : Error<"expected a header name after '%0'">;
|
||||||
|
@ -429,6 +431,9 @@ def err_mmap_explicit_top_level : Error<
|
||||||
def err_mmap_nested_submodule_id : Error<
|
def err_mmap_nested_submodule_id : Error<
|
||||||
"qualified module name can only be used to define modules at the top level">;
|
"qualified module name can only be used to define modules at the top level">;
|
||||||
def err_mmap_expected_feature : Error<"expected a feature name">;
|
def err_mmap_expected_feature : Error<"expected a feature name">;
|
||||||
|
def err_mmap_expected_attribute : Error<"expected an attribute name">;
|
||||||
|
def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">,
|
||||||
|
InGroup<IgnoredAttributes>;
|
||||||
|
|
||||||
def warn_auto_module_import : Warning<
|
def warn_auto_module_import : Warning<
|
||||||
"treating #%select{include|import|include_next|__include_macros}0 as an "
|
"treating #%select{include|import|include_next|__include_macros}0 as an "
|
||||||
|
|
|
@ -86,6 +86,10 @@ public:
|
||||||
/// \brief Whether this is an explicit submodule.
|
/// \brief Whether this is an explicit submodule.
|
||||||
unsigned IsExplicit : 1;
|
unsigned IsExplicit : 1;
|
||||||
|
|
||||||
|
/// \brief Whether this is a "system" module (which assumes that all
|
||||||
|
/// headers in it are system headers).
|
||||||
|
unsigned IsSystem : 1;
|
||||||
|
|
||||||
/// \brief Whether we should infer submodules for this module based on
|
/// \brief Whether we should infer submodules for this module based on
|
||||||
/// the headers.
|
/// the headers.
|
||||||
///
|
///
|
||||||
|
@ -154,7 +158,8 @@ public:
|
||||||
bool IsFramework)
|
bool IsFramework)
|
||||||
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), Umbrella(),
|
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), Umbrella(),
|
||||||
IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
|
IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
|
||||||
IsExplicit(false), InferSubmodules(false), InferExplicitSubmodules(false),
|
IsExplicit(false), IsSystem(false),
|
||||||
|
InferSubmodules(false), InferExplicitSubmodules(false),
|
||||||
InferExportWildcard(false), NameVisibility(Hidden) { }
|
InferExportWildcard(false), NameVisibility(Hidden) { }
|
||||||
|
|
||||||
/// \brief Construct a new module or submodule.
|
/// \brief Construct a new module or submodule.
|
||||||
|
|
|
@ -618,9 +618,10 @@ public:
|
||||||
FileID getMainFileID() const { return MainFileID; }
|
FileID getMainFileID() const { return MainFileID; }
|
||||||
|
|
||||||
/// createMainFileID - Create the FileID for the main source file.
|
/// createMainFileID - Create the FileID for the main source file.
|
||||||
FileID createMainFileID(const FileEntry *SourceFile) {
|
FileID createMainFileID(const FileEntry *SourceFile,
|
||||||
|
SrcMgr::CharacteristicKind Kind = SrcMgr::C_User) {
|
||||||
assert(MainFileID.isInvalid() && "MainFileID already set!");
|
assert(MainFileID.isInvalid() && "MainFileID already set!");
|
||||||
MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
|
MainFileID = createFileID(SourceFile, SourceLocation(), Kind);
|
||||||
return MainFileID;
|
return MainFileID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
|
#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_
|
||||||
|
|
||||||
#include "clang/Frontend/CompilerInvocation.h"
|
#include "clang/Frontend/CompilerInvocation.h"
|
||||||
|
#include "clang/Basic/SourceManager.h"
|
||||||
#include "clang/Lex/ModuleLoader.h"
|
#include "clang/Lex/ModuleLoader.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
@ -627,13 +628,15 @@ public:
|
||||||
/// as the main file.
|
/// as the main file.
|
||||||
///
|
///
|
||||||
/// \return True on success.
|
/// \return True on success.
|
||||||
bool InitializeSourceManager(StringRef InputFile);
|
bool InitializeSourceManager(StringRef InputFile,
|
||||||
|
SrcMgr::CharacteristicKind Kind = SrcMgr::C_User);
|
||||||
|
|
||||||
/// InitializeSourceManager - Initialize the source manager to set InputFile
|
/// InitializeSourceManager - Initialize the source manager to set InputFile
|
||||||
/// as the main file.
|
/// as the main file.
|
||||||
///
|
///
|
||||||
/// \return True on success.
|
/// \return True on success.
|
||||||
static bool InitializeSourceManager(StringRef InputFile,
|
static bool InitializeSourceManager(StringRef InputFile,
|
||||||
|
SrcMgr::CharacteristicKind Kind,
|
||||||
DiagnosticsEngine &Diags,
|
DiagnosticsEngine &Diags,
|
||||||
FileManager &FileMgr,
|
FileManager &FileMgr,
|
||||||
SourceManager &SourceMgr,
|
SourceManager &SourceMgr,
|
||||||
|
|
|
@ -76,9 +76,12 @@ struct FrontendInputFile {
|
||||||
/// \brief The kind of input, e.g., C source, AST file, LLVM IR.
|
/// \brief The kind of input, e.g., C source, AST file, LLVM IR.
|
||||||
InputKind Kind;
|
InputKind Kind;
|
||||||
|
|
||||||
|
/// \brief Whether we're dealing with a 'system' input (vs. a 'user' input).
|
||||||
|
bool IsSystem;
|
||||||
|
|
||||||
FrontendInputFile() : Kind(IK_None) { }
|
FrontendInputFile() : Kind(IK_None) { }
|
||||||
FrontendInputFile(StringRef File, InputKind Kind)
|
FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false)
|
||||||
: File(File.str()), Kind(Kind) { }
|
: File(File.str()), Kind(Kind), IsSystem(IsSystem) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// FrontendOptions - Options for controlling the behavior of the frontend.
|
/// FrontendOptions - Options for controlling the behavior of the frontend.
|
||||||
|
|
|
@ -401,9 +401,13 @@ public:
|
||||||
///
|
///
|
||||||
/// \param Dir The framework directory (e.g., ModuleName.framework).
|
/// \param Dir The framework directory (e.g., ModuleName.framework).
|
||||||
///
|
///
|
||||||
|
/// \param IsSystem Whether the framework directory is part of the system
|
||||||
|
/// frameworks.
|
||||||
|
///
|
||||||
/// \returns The module, if found; otherwise, null.
|
/// \returns The module, if found; otherwise, null.
|
||||||
Module *getFrameworkModule(StringRef Name,
|
Module *getFrameworkModule(StringRef Name,
|
||||||
const DirectoryEntry *Dir);
|
const DirectoryEntry *Dir,
|
||||||
|
bool IsSystem);
|
||||||
|
|
||||||
/// \brief Retrieve the module map.
|
/// \brief Retrieve the module map.
|
||||||
ModuleMap &getModuleMap() { return ModMap; }
|
ModuleMap &getModuleMap() { return ModMap; }
|
||||||
|
|
|
@ -159,7 +159,7 @@ public:
|
||||||
/// framework directory.
|
/// framework directory.
|
||||||
Module *inferFrameworkModule(StringRef ModuleName,
|
Module *inferFrameworkModule(StringRef ModuleName,
|
||||||
const DirectoryEntry *FrameworkDir,
|
const DirectoryEntry *FrameworkDir,
|
||||||
Module *Parent);
|
bool IsSystem, Module *Parent);
|
||||||
|
|
||||||
/// \brief Retrieve the module map file containing the definition of the given
|
/// \brief Retrieve the module map file containing the definition of the given
|
||||||
/// module.
|
/// module.
|
||||||
|
|
|
@ -24,9 +24,9 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
|
||||||
bool IsFramework, bool IsExplicit)
|
bool IsFramework, bool IsExplicit)
|
||||||
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
|
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
|
||||||
Umbrella(), IsAvailable(true), IsFromModuleFile(false),
|
Umbrella(), IsAvailable(true), IsFromModuleFile(false),
|
||||||
IsFramework(IsFramework), IsExplicit(IsExplicit), InferSubmodules(false),
|
IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
|
||||||
InferExplicitSubmodules(false), InferExportWildcard(false),
|
InferSubmodules(false), InferExplicitSubmodules(false),
|
||||||
NameVisibility(Hidden)
|
InferExportWildcard(false), NameVisibility(Hidden)
|
||||||
{
|
{
|
||||||
if (Parent) {
|
if (Parent) {
|
||||||
if (!Parent->isAvailable())
|
if (!Parent->isAvailable())
|
||||||
|
@ -172,7 +172,14 @@ void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
|
||||||
OS << "framework ";
|
OS << "framework ";
|
||||||
if (IsExplicit)
|
if (IsExplicit)
|
||||||
OS << "explicit ";
|
OS << "explicit ";
|
||||||
OS << "module " << Name << " {\n";
|
OS << "module " << Name;
|
||||||
|
|
||||||
|
if (IsSystem) {
|
||||||
|
OS.indent(Indent + 2);
|
||||||
|
OS << " [system]";
|
||||||
|
}
|
||||||
|
|
||||||
|
OS << " {\n";
|
||||||
|
|
||||||
if (!Requires.empty()) {
|
if (!Requires.empty()) {
|
||||||
OS.indent(Indent + 2);
|
OS.indent(Indent + 2);
|
||||||
|
|
|
@ -577,12 +577,15 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
|
||||||
|
|
||||||
// Initialization Utilities
|
// Initialization Utilities
|
||||||
|
|
||||||
bool CompilerInstance::InitializeSourceManager(StringRef InputFile) {
|
bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
|
||||||
return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
|
SrcMgr::CharacteristicKind Kind){
|
||||||
getSourceManager(), getFrontendOpts());
|
return InitializeSourceManager(InputFile, Kind, getDiagnostics(),
|
||||||
|
getFileManager(), getSourceManager(),
|
||||||
|
getFrontendOpts());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
|
bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
|
||||||
|
SrcMgr::CharacteristicKind Kind,
|
||||||
DiagnosticsEngine &Diags,
|
DiagnosticsEngine &Diags,
|
||||||
FileManager &FileMgr,
|
FileManager &FileMgr,
|
||||||
SourceManager &SourceMgr,
|
SourceManager &SourceMgr,
|
||||||
|
@ -594,7 +597,7 @@ bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
|
||||||
Diags.Report(diag::err_fe_error_reading) << InputFile;
|
Diags.Report(diag::err_fe_error_reading) << InputFile;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SourceMgr.createMainFileID(File);
|
SourceMgr.createMainFileID(File, Kind);
|
||||||
} else {
|
} else {
|
||||||
llvm::OwningPtr<llvm::MemoryBuffer> SB;
|
llvm::OwningPtr<llvm::MemoryBuffer> SB;
|
||||||
if (llvm::MemoryBuffer::getSTDIN(SB)) {
|
if (llvm::MemoryBuffer::getSTDIN(SB)) {
|
||||||
|
@ -604,7 +607,7 @@ bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
|
||||||
}
|
}
|
||||||
const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
|
const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
|
||||||
SB->getBufferSize(), 0);
|
SB->getBufferSize(), 0);
|
||||||
SourceMgr.createMainFileID(File);
|
SourceMgr.createMainFileID(File, Kind);
|
||||||
SourceMgr.overrideFileContents(File, SB.take());
|
SourceMgr.overrideFileContents(File, SB.take());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -320,7 +320,10 @@ void FrontendAction::Execute() {
|
||||||
// Initialize the main file entry. This needs to be delayed until after PCH
|
// Initialize the main file entry. This needs to be delayed until after PCH
|
||||||
// has loaded.
|
// has loaded.
|
||||||
if (!isCurrentFileAST()) {
|
if (!isCurrentFileAST()) {
|
||||||
if (!CI.InitializeSourceManager(getCurrentFile()))
|
if (!CI.InitializeSourceManager(getCurrentFile(),
|
||||||
|
getCurrentInput().IsSystem
|
||||||
|
? SrcMgr::C_System
|
||||||
|
: SrcMgr::C_User))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -256,7 +256,8 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
|
||||||
// Simple case: we have an umbrella header and there are no additional
|
// Simple case: we have an umbrella header and there are no additional
|
||||||
// includes, we can just parse the umbrella header directly.
|
// includes, we can just parse the umbrella header directly.
|
||||||
setCurrentInput(FrontendInputFile(UmbrellaHeader->getName(),
|
setCurrentInput(FrontendInputFile(UmbrellaHeader->getName(),
|
||||||
getCurrentFileKind()));
|
getCurrentFileKind(),
|
||||||
|
Module->IsSystem));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +314,8 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
|
||||||
llvm::MemoryBuffer *HeaderContentsBuf
|
llvm::MemoryBuffer *HeaderContentsBuf
|
||||||
= llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
|
= llvm::MemoryBuffer::getMemBufferCopy(HeaderContents);
|
||||||
CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
|
CI.getSourceManager().overrideFileContents(HeaderFile, HeaderContentsBuf);
|
||||||
setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind()));
|
setCurrentInput(FrontendInputFile(HeaderName, getCurrentFileKind(),
|
||||||
|
Module->IsSystem));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,9 @@ const FileEntry *HeaderSearch::lookupModule(StringRef ModuleName,
|
||||||
llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework");
|
llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework");
|
||||||
if (const DirectoryEntry *FrameworkDir
|
if (const DirectoryEntry *FrameworkDir
|
||||||
= FileMgr.getDirectory(FrameworkDirName)) {
|
= FileMgr.getDirectory(FrameworkDirName)) {
|
||||||
Module = getFrameworkModule(ModuleName, FrameworkDir);
|
bool IsSystem
|
||||||
|
= SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User;
|
||||||
|
Module = getFrameworkModule(ModuleName, FrameworkDir, IsSystem);
|
||||||
if (Module)
|
if (Module)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -319,8 +321,10 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
|
||||||
Module *Module = 0;
|
Module *Module = 0;
|
||||||
if (SuggestedModule) {
|
if (SuggestedModule) {
|
||||||
if (const DirectoryEntry *FrameworkDir
|
if (const DirectoryEntry *FrameworkDir
|
||||||
= FileMgr.getDirectory(FrameworkName))
|
= FileMgr.getDirectory(FrameworkName)) {
|
||||||
Module = HS.getFrameworkModule(ModuleName, FrameworkDir);
|
bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
|
||||||
|
Module = HS.getFrameworkModule(ModuleName, FrameworkDir, IsSystem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
|
// Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
|
||||||
|
@ -858,7 +862,8 @@ Module *HeaderSearch::getModule(StringRef Name, bool AllowSearch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Module *HeaderSearch::getFrameworkModule(StringRef Name,
|
Module *HeaderSearch::getFrameworkModule(StringRef Name,
|
||||||
const DirectoryEntry *Dir) {
|
const DirectoryEntry *Dir,
|
||||||
|
bool IsSystem) {
|
||||||
if (Module *Module = ModMap.findModule(Name))
|
if (Module *Module = ModMap.findModule(Name))
|
||||||
return Module;
|
return Module;
|
||||||
|
|
||||||
|
@ -908,6 +913,7 @@ Module *HeaderSearch::getFrameworkModule(StringRef Name,
|
||||||
// Try to infer a module map from the top-level framework directory.
|
// Try to infer a module map from the top-level framework directory.
|
||||||
Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(),
|
Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(),
|
||||||
TopFrameworkDir,
|
TopFrameworkDir,
|
||||||
|
IsSystem,
|
||||||
/*Parent=*/0);
|
/*Parent=*/0);
|
||||||
|
|
||||||
// Follow the submodule path to find the requested (sub)framework module
|
// Follow the submodule path to find the requested (sub)framework module
|
||||||
|
|
|
@ -284,6 +284,7 @@ ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
|
||||||
Module *
|
Module *
|
||||||
ModuleMap::inferFrameworkModule(StringRef ModuleName,
|
ModuleMap::inferFrameworkModule(StringRef ModuleName,
|
||||||
const DirectoryEntry *FrameworkDir,
|
const DirectoryEntry *FrameworkDir,
|
||||||
|
bool IsSystem,
|
||||||
Module *Parent) {
|
Module *Parent) {
|
||||||
// Check whether we've already found this module.
|
// Check whether we've already found this module.
|
||||||
if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
|
if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
|
||||||
|
@ -305,6 +306,9 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
|
||||||
|
|
||||||
Module *Result = new Module(ModuleName, SourceLocation(), Parent,
|
Module *Result = new Module(ModuleName, SourceLocation(), Parent,
|
||||||
/*IsFramework=*/true, /*IsExplicit=*/false);
|
/*IsFramework=*/true, /*IsExplicit=*/false);
|
||||||
|
if (IsSystem)
|
||||||
|
Result->IsSystem = IsSystem;
|
||||||
|
|
||||||
if (!Parent)
|
if (!Parent)
|
||||||
Modules[ModuleName] = Result;
|
Modules[ModuleName] = Result;
|
||||||
|
|
||||||
|
@ -338,7 +342,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
|
||||||
= FileMgr.getDirectory(Dir->path())) {
|
= FileMgr.getDirectory(Dir->path())) {
|
||||||
// FIXME: Do we want to warn about subframeworks without umbrella headers?
|
// FIXME: Do we want to warn about subframeworks without umbrella headers?
|
||||||
inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
|
inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
|
||||||
Result);
|
IsSystem, Result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,7 +458,9 @@ namespace clang {
|
||||||
Star,
|
Star,
|
||||||
StringLiteral,
|
StringLiteral,
|
||||||
LBrace,
|
LBrace,
|
||||||
RBrace
|
RBrace,
|
||||||
|
LSquare,
|
||||||
|
RSquare
|
||||||
} Kind;
|
} Kind;
|
||||||
|
|
||||||
unsigned Location;
|
unsigned Location;
|
||||||
|
@ -579,6 +585,10 @@ retry:
|
||||||
Tok.Kind = MMToken::LBrace;
|
Tok.Kind = MMToken::LBrace;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case tok::l_square:
|
||||||
|
Tok.Kind = MMToken::LSquare;
|
||||||
|
break;
|
||||||
|
|
||||||
case tok::period:
|
case tok::period:
|
||||||
Tok.Kind = MMToken::Period;
|
Tok.Kind = MMToken::Period;
|
||||||
break;
|
break;
|
||||||
|
@ -587,6 +597,10 @@ retry:
|
||||||
Tok.Kind = MMToken::RBrace;
|
Tok.Kind = MMToken::RBrace;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case tok::r_square:
|
||||||
|
Tok.Kind = MMToken::RSquare;
|
||||||
|
break;
|
||||||
|
|
||||||
case tok::star:
|
case tok::star:
|
||||||
Tok.Kind = MMToken::Star;
|
Tok.Kind = MMToken::Star;
|
||||||
break;
|
break;
|
||||||
|
@ -625,18 +639,26 @@ retry:
|
||||||
|
|
||||||
void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
|
void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
|
||||||
unsigned braceDepth = 0;
|
unsigned braceDepth = 0;
|
||||||
|
unsigned squareDepth = 0;
|
||||||
do {
|
do {
|
||||||
switch (Tok.Kind) {
|
switch (Tok.Kind) {
|
||||||
case MMToken::EndOfFile:
|
case MMToken::EndOfFile:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case MMToken::LBrace:
|
case MMToken::LBrace:
|
||||||
if (Tok.is(K) && braceDepth == 0)
|
if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
++braceDepth;
|
++braceDepth;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MMToken::LSquare:
|
||||||
|
if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
++squareDepth;
|
||||||
|
break;
|
||||||
|
|
||||||
case MMToken::RBrace:
|
case MMToken::RBrace:
|
||||||
if (braceDepth > 0)
|
if (braceDepth > 0)
|
||||||
--braceDepth;
|
--braceDepth;
|
||||||
|
@ -644,8 +666,15 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MMToken::RSquare:
|
||||||
|
if (squareDepth > 0)
|
||||||
|
--squareDepth;
|
||||||
|
else if (Tok.is(K))
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (braceDepth == 0 && Tok.is(K))
|
if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -681,10 +710,28 @@ bool ModuleMapParser::parseModuleId(ModuleId &Id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/// \brief Enumerates the known attributes.
|
||||||
|
enum AttributeKind {
|
||||||
|
/// \brief An unknown attribute.
|
||||||
|
AT_unknown,
|
||||||
|
/// \brief The 'system' attribute.
|
||||||
|
AT_system
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Parse a module declaration.
|
/// \brief Parse a module declaration.
|
||||||
///
|
///
|
||||||
/// module-declaration:
|
/// module-declaration:
|
||||||
/// 'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* }
|
/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
|
||||||
|
/// { module-member* }
|
||||||
|
///
|
||||||
|
/// attributes:
|
||||||
|
/// attribute attributes
|
||||||
|
/// attribute
|
||||||
|
///
|
||||||
|
/// attribute:
|
||||||
|
/// [ identifier ]
|
||||||
///
|
///
|
||||||
/// module-member:
|
/// module-member:
|
||||||
/// requires-declaration
|
/// requires-declaration
|
||||||
|
@ -777,6 +824,49 @@ void ModuleMapParser::parseModuleDecl() {
|
||||||
StringRef ModuleName = Id.back().first;
|
StringRef ModuleName = Id.back().first;
|
||||||
SourceLocation ModuleNameLoc = Id.back().second;
|
SourceLocation ModuleNameLoc = Id.back().second;
|
||||||
|
|
||||||
|
// Parse the optional attribute list.
|
||||||
|
bool IsSystem = false;
|
||||||
|
while (Tok.is(MMToken::LSquare)) {
|
||||||
|
// Consume the '['.
|
||||||
|
SourceLocation LSquareLoc = consumeToken();
|
||||||
|
|
||||||
|
// Check whether we have an attribute name here.
|
||||||
|
if (!Tok.is(MMToken::Identifier)) {
|
||||||
|
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
|
||||||
|
skipUntil(MMToken::RSquare);
|
||||||
|
if (Tok.is(MMToken::RSquare))
|
||||||
|
consumeToken();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the attribute name.
|
||||||
|
AttributeKind Attribute
|
||||||
|
= llvm::StringSwitch<AttributeKind>(Tok.getString())
|
||||||
|
.Case("system", AT_system)
|
||||||
|
.Default(AT_unknown);
|
||||||
|
switch (Attribute) {
|
||||||
|
case AT_unknown:
|
||||||
|
Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
|
||||||
|
<< Tok.getString();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AT_system:
|
||||||
|
IsSystem = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
consumeToken();
|
||||||
|
|
||||||
|
// Consume the ']'.
|
||||||
|
if (!Tok.is(MMToken::RSquare)) {
|
||||||
|
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
|
||||||
|
Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
|
||||||
|
skipUntil(MMToken::RSquare);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Tok.is(MMToken::RSquare))
|
||||||
|
consumeToken();
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the opening brace.
|
// Parse the opening brace.
|
||||||
if (!Tok.is(MMToken::LBrace)) {
|
if (!Tok.is(MMToken::LBrace)) {
|
||||||
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
|
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
|
||||||
|
@ -818,6 +908,8 @@ void ModuleMapParser::parseModuleDecl() {
|
||||||
ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
|
ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
|
||||||
Explicit).first;
|
Explicit).first;
|
||||||
ActiveModule->DefinitionLoc = ModuleNameLoc;
|
ActiveModule->DefinitionLoc = ModuleNameLoc;
|
||||||
|
if (IsSystem)
|
||||||
|
ActiveModule->IsSystem = true;
|
||||||
|
|
||||||
bool Done = false;
|
bool Done = false;
|
||||||
do {
|
do {
|
||||||
|
@ -1251,8 +1343,10 @@ bool ModuleMapParser::parseModuleMapFile() {
|
||||||
case MMToken::HeaderKeyword:
|
case MMToken::HeaderKeyword:
|
||||||
case MMToken::Identifier:
|
case MMToken::Identifier:
|
||||||
case MMToken::LBrace:
|
case MMToken::LBrace:
|
||||||
|
case MMToken::LSquare:
|
||||||
case MMToken::Period:
|
case MMToken::Period:
|
||||||
case MMToken::RBrace:
|
case MMToken::RBrace:
|
||||||
|
case MMToken::RSquare:
|
||||||
case MMToken::RequiresKeyword:
|
case MMToken::RequiresKeyword:
|
||||||
case MMToken::Star:
|
case MMToken::Star:
|
||||||
case MMToken::StringLiteral:
|
case MMToken::StringLiteral:
|
||||||
|
|
|
@ -3130,9 +3130,10 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
||||||
SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]);
|
SubmoduleID Parent = getGlobalSubmoduleID(F, Record[1]);
|
||||||
bool IsFramework = Record[2];
|
bool IsFramework = Record[2];
|
||||||
bool IsExplicit = Record[3];
|
bool IsExplicit = Record[3];
|
||||||
bool InferSubmodules = Record[4];
|
bool IsSystem = Record[4];
|
||||||
bool InferExplicitSubmodules = Record[5];
|
bool InferSubmodules = Record[5];
|
||||||
bool InferExportWildcard = Record[6];
|
bool InferExplicitSubmodules = Record[6];
|
||||||
|
bool InferExportWildcard = Record[7];
|
||||||
|
|
||||||
Module *ParentModule = 0;
|
Module *ParentModule = 0;
|
||||||
if (Parent)
|
if (Parent)
|
||||||
|
@ -3151,6 +3152,7 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentModule->IsFromModuleFile = true;
|
CurrentModule->IsFromModuleFile = true;
|
||||||
|
CurrentModule->IsSystem = IsSystem || CurrentModule->IsSystem;
|
||||||
CurrentModule->InferSubmodules = InferSubmodules;
|
CurrentModule->InferSubmodules = InferSubmodules;
|
||||||
CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
|
CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
|
||||||
CurrentModule->InferExportWildcard = InferExportWildcard;
|
CurrentModule->InferExportWildcard = InferExportWildcard;
|
||||||
|
|
|
@ -1897,8 +1897,9 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
|
||||||
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
|
||||||
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules...
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
|
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
|
||||||
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
|
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
|
||||||
unsigned DefinitionAbbrev = Stream.EmitAbbrev(Abbrev);
|
unsigned DefinitionAbbrev = Stream.EmitAbbrev(Abbrev);
|
||||||
|
@ -1949,6 +1950,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
||||||
}
|
}
|
||||||
Record.push_back(Mod->IsFramework);
|
Record.push_back(Mod->IsFramework);
|
||||||
Record.push_back(Mod->IsExplicit);
|
Record.push_back(Mod->IsExplicit);
|
||||||
|
Record.push_back(Mod->IsSystem);
|
||||||
Record.push_back(Mod->InferSubmodules);
|
Record.push_back(Mod->InferSubmodules);
|
||||||
Record.push_back(Mod->InferExplicitSubmodules);
|
Record.push_back(Mod->InferExplicitSubmodules);
|
||||||
Record.push_back(Mod->InferExportWildcard);
|
Record.push_back(Mod->InferExportWildcard);
|
||||||
|
|
|
@ -1 +1,8 @@
|
||||||
int no_umbrella_A;
|
int no_umbrella_A;
|
||||||
|
|
||||||
|
inline int has_warning(int x) {
|
||||||
|
if (x > 0)
|
||||||
|
return x;
|
||||||
|
// Note: warning here is suppressed because this module is considered a
|
||||||
|
// "system" module.
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
framework module NoUmbrella {
|
framework module NoUmbrella [system] {
|
||||||
umbrella "Headers"
|
umbrella "Headers"
|
||||||
module * { }
|
module * { }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue