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:
Douglas Gregor 2012-01-27 19:52:33 +00:00
parent 63fe5697f4
commit a686e1b05d
17 changed files with 189 additions and 42 deletions

View File

@ -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 "

View File

@ -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.

View File

@ -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;
} }

View File

@ -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,

View File

@ -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.

View File

@ -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; }

View File

@ -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.

View File

@ -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);

View File

@ -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());
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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.
}

View File

@ -1,4 +1,4 @@
framework module NoUmbrella { framework module NoUmbrella [system] {
umbrella "Headers" umbrella "Headers"
module * { } module * { }