r342304 - [modules] Frontend support for building a header module from a list of
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 14 18:21:15 PDT 2018
Author: rsmith
Date: Fri Sep 14 18:21:15 2018
New Revision: 342304
URL: http://llvm.org/viewvc/llvm-project?rev=342304&view=rev
Log:
[modules] Frontend support for building a header module from a list of
headaer files.
Added:
cfe/trunk/test/Modules/Inputs/no-module-map/
cfe/trunk/test/Modules/Inputs/no-module-map/a.h
cfe/trunk/test/Modules/Inputs/no-module-map/b.h
cfe/trunk/test/Modules/no-module-map.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
cfe/trunk/include/clang/Basic/DiagnosticIDs.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Basic/LangOptions.h
cfe/trunk/include/clang/Driver/CC1Options.td
cfe/trunk/include/clang/Frontend/FrontendAction.h
cfe/trunk/include/clang/Frontend/FrontendActions.h
cfe/trunk/include/clang/Frontend/FrontendOptions.h
cfe/trunk/include/clang/Lex/ModuleMap.h
cfe/trunk/lib/Frontend/CompilerInstance.cpp
cfe/trunk/lib/Frontend/CompilerInvocation.cpp
cfe/trunk/lib/Frontend/FrontendAction.cpp
cfe/trunk/lib/Frontend/FrontendActions.cpp
cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp
cfe/trunk/lib/Lex/ModuleMap.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Fri Sep 14 18:21:15 2018
@@ -187,6 +187,8 @@ def err_module_build_requires_fmodules :
"module compilation requires '-fmodules'">;
def err_module_interface_requires_modules_ts : Error<
"module interface compilation requires '-fmodules-ts'">;
+def err_header_module_requires_modules : Error<
+ "header module compilation requires '-fmodules' or '-fmodules-ts'">;
def warn_module_config_mismatch : Warning<
"module file %0 cannot be loaded due to a configuration mismatch with the current "
"compilation">, InGroup<DiagGroup<"module-file-config-mismatch">>, DefaultError;
@@ -224,6 +226,10 @@ def remark_module_build_done : Remark<"f
def err_modules_embed_file_not_found :
Error<"file '%0' specified by '-fmodules-embed-file=' not found">,
DefaultFatal;
+def err_module_header_file_not_found :
+ Error<"module header file '%0' not found">, DefaultFatal;
+def err_module_header_file_invalid :
+ Error<"unexpected module header file input '%0'">, DefaultFatal;
def err_test_module_file_extension_version : Error<
"test module file extension '%0' has different version (%1.%2) than expected "
Modified: cfe/trunk/include/clang/Basic/DiagnosticIDs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticIDs.h?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticIDs.h (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticIDs.h Fri Sep 14 18:21:15 2018
@@ -30,7 +30,7 @@ namespace clang {
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 200,
- DIAG_SIZE_FRONTEND = 100,
+ DIAG_SIZE_FRONTEND = 150,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 400,
DIAG_SIZE_PARSE = 500,
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep 14 18:21:15 2018
@@ -9090,6 +9090,8 @@ def err_invalid_type_for_program_scope_v
let CategoryName = "Modules Issue" in {
def err_module_decl_in_module_map_module : Error<
"'module' declaration found while building module from module map">;
+def err_module_decl_in_header_module : Error<
+ "'module' declaration found while building header module">;
def err_module_interface_implementation_mismatch : Error<
"missing 'export' specifier in module declaration while "
"building module interface">;
Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Fri Sep 14 18:21:15 2018
@@ -73,8 +73,11 @@ public:
/// Compiling a module from a module map.
CMK_ModuleMap,
+ /// Compiling a module from a list of header files.
+ CMK_HeaderModule,
+
/// Compiling a C++ modules TS module interface unit.
- CMK_ModuleInterface
+ CMK_ModuleInterface,
};
enum PragmaMSPointersToMembersKind {
Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Fri Sep 14 18:21:15 2018
@@ -543,6 +543,8 @@ def emit_module : Flag<["-"], "emit-modu
HelpText<"Generate pre-compiled module file from a module map">;
def emit_module_interface : Flag<["-"], "emit-module-interface">,
HelpText<"Generate pre-compiled module file from a C++ module interface">;
+def emit_header_module : Flag<["-"], "emit-header-module">,
+ HelpText<"Generate pre-compiled module file from a set of header files">;
def emit_pth : Flag<["-"], "emit-pth">,
HelpText<"Generate pre-tokenized header file">;
def emit_pch : Flag<["-"], "emit-pch">,
Modified: cfe/trunk/include/clang/Frontend/FrontendAction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendAction.h?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendAction.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendAction.h Fri Sep 14 18:21:15 2018
@@ -48,6 +48,12 @@ protected:
/// @name Implementation Action Interface
/// @{
+ /// Prepare to execute the action on the given CompilerInstance.
+ ///
+ /// This is called before executing the action on any inputs, and can modify
+ /// the configuration as needed (including adjusting the input list).
+ virtual bool PrepareToExecuteAction(CompilerInstance &CI) { return true; }
+
/// Create the AST consumer object for this action, if supported.
///
/// This routine is called as part of BeginSourceFile(), which will
@@ -130,11 +136,18 @@ public:
return CurrentInput;
}
- const StringRef getCurrentFile() const {
+ StringRef getCurrentFile() const {
assert(!CurrentInput.isEmpty() && "No current file!");
return CurrentInput.getFile();
}
+ StringRef getCurrentFileOrBufferName() const {
+ assert(!CurrentInput.isEmpty() && "No current file!");
+ return CurrentInput.isFile()
+ ? CurrentInput.getFile()
+ : CurrentInput.getBuffer()->getBufferIdentifier();
+ }
+
InputKind getCurrentFileKind() const {
assert(!CurrentInput.isEmpty() && "No current file!");
return CurrentInput.getKind();
@@ -190,6 +203,11 @@ public:
/// @name Public Action Interface
/// @{
+ /// Prepare the action to execute on the given compiler instance.
+ bool PrepareToExecute(CompilerInstance &CI) {
+ return PrepareToExecuteAction(CI);
+ }
+
/// Prepare the action for processing the input file \p Input.
///
/// This is run after the options and frontend have been initialized,
Modified: cfe/trunk/include/clang/Frontend/FrontendActions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendActions.h?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendActions.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendActions.h Fri Sep 14 18:21:15 2018
@@ -142,6 +142,19 @@ private:
CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
};
+class GenerateHeaderModuleAction : public GenerateModuleAction {
+ /// The synthesized module input buffer for the current compilation.
+ std::unique_ptr<llvm::MemoryBuffer> Buffer;
+ std::vector<std::string> ModuleHeaders;
+
+private:
+ bool PrepareToExecuteAction(CompilerInstance &CI) override;
+ bool BeginSourceFileAction(CompilerInstance &CI) override;
+
+ std::unique_ptr<raw_pwrite_stream>
+ CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
+};
+
class SyntaxOnlyAction : public ASTFrontendAction {
protected:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
Modified: cfe/trunk/include/clang/Frontend/FrontendOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendOptions.h?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendOptions.h Fri Sep 14 18:21:15 2018
@@ -82,6 +82,9 @@ enum ActionKind {
/// Generate pre-compiled module from a C++ module interface file.
GenerateModuleInterface,
+ /// Generate pre-compiled module from a set of header files.
+ GenerateHeaderModule,
+
/// Generate pre-compiled header.
GeneratePCH,
Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Fri Sep 14 18:21:15 2018
@@ -92,9 +92,9 @@ class ModuleMap {
/// named LangOpts::CurrentModule, if we've loaded it).
Module *SourceModule = nullptr;
- /// The global module for the current TU, if we still own it. (Ownership is
- /// transferred if/when we create an enclosing module.
- std::unique_ptr<Module> PendingGlobalModule;
+ /// Submodules of the current module that have not yet been attached to it.
+ /// (Ownership is transferred if/when we create an enclosing module.)
+ llvm::SmallVector<std::unique_ptr<Module>, 8> PendingSubmodules;
/// The top-level modules that are known.
llvm::StringMap<Module *> Modules;
@@ -519,8 +519,7 @@ public:
bool IsFramework,
bool IsExplicit);
- /// Create a 'global module' for a C++ Modules TS module interface
- /// unit.
+ /// Create a 'global module' for a C++ Modules TS module interface unit.
///
/// We model the global module as a submodule of the module interface unit.
/// Unfortunately, we can't create the module interface unit's Module until
@@ -537,6 +536,9 @@ public:
Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name,
Module *GlobalModule);
+ /// Create a header module from the specified list of headers.
+ Module *createHeaderModule(StringRef Name, ArrayRef<Module::Header> Headers);
+
/// Infer the contents of a framework module map from the given
/// framework directory.
Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir,
Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Fri Sep 14 18:21:15 2018
@@ -911,6 +911,9 @@ bool CompilerInstance::ExecuteAction(Fro
// taking it as an input instead of hard-coding llvm::errs.
raw_ostream &OS = llvm::errs();
+ if (!Act.PrepareToExecute(*this))
+ return false;
+
// Create the target instance.
setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
getInvocation().TargetOpts));
@@ -1615,22 +1618,7 @@ CompilerInstance::loadModule(SourceLocat
Module::NameVisibilityKind Visibility,
bool IsInclusionDirective) {
// Determine what file we're searching from.
- // FIXME: Should we be deciding whether this is a submodule (here and
- // below) based on -fmodules-ts or should we pass a flag and make the
- // caller decide?
- std::string ModuleName;
- if (getLangOpts().ModulesTS) {
- // FIXME: Same code as Sema::ActOnModuleDecl() so there is probably a
- // better place/way to do this.
- for (auto &Piece : Path) {
- if (!ModuleName.empty())
- ModuleName += ".";
- ModuleName += Piece.first->getName();
- }
- }
- else
- ModuleName = Path[0].first->getName();
-
+ StringRef ModuleName = Path[0].first->getName();
SourceLocation ModuleNameLoc = Path[0].second;
// If we've already handled this import, just return the cached result.
@@ -1859,7 +1847,7 @@ CompilerInstance::loadModule(SourceLocat
// Verify that the rest of the module path actually corresponds to
// a submodule.
bool MapPrivateSubModToTopLevel = false;
- if (!getLangOpts().ModulesTS && Path.size() > 1) {
+ if (Path.size() > 1) {
for (unsigned I = 1, N = Path.size(); I != N; ++I) {
StringRef Name = Path[I].first->getName();
clang::Module *Sub = Module->findSubmodule(Name);
Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Fri Sep 14 18:21:15 2018
@@ -1454,6 +1454,8 @@ static InputKind ParseFrontendArgs(Front
Opts.ProgramAction = frontend::GenerateModule; break;
case OPT_emit_module_interface:
Opts.ProgramAction = frontend::GenerateModuleInterface; break;
+ case OPT_emit_header_module:
+ Opts.ProgramAction = frontend::GenerateHeaderModule; break;
case OPT_emit_pch:
Opts.ProgramAction = frontend::GeneratePCH; break;
case OPT_emit_pth:
@@ -2830,6 +2832,7 @@ static bool isStrictlyPreprocessorAction
case frontend::FixIt:
case frontend::GenerateModule:
case frontend::GenerateModuleInterface:
+ case frontend::GenerateHeaderModule:
case frontend::GeneratePCH:
case frontend::GeneratePTH:
case frontend::ParseSyntaxOnly:
Modified: cfe/trunk/lib/Frontend/FrontendAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendAction.cpp?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendAction.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendAction.cpp Fri Sep 14 18:21:15 2018
@@ -523,7 +523,6 @@ bool FrontendAction::BeginSourceFile(Com
setCurrentInput(Input);
setCompilerInstance(&CI);
- StringRef InputFile = Input.getFile();
bool HasBegunSourceFile = false;
bool ReplayASTFile = Input.getKind().getFormat() == InputKind::Precompiled &&
usesPreprocessorOnly();
@@ -541,6 +540,9 @@ bool FrontendAction::BeginSourceFile(Com
&Diags->getDiagnosticOptions()));
ASTDiags->setClient(Diags->getClient(), /*OwnsClient*/false);
+ // FIXME: What if the input is a memory buffer?
+ StringRef InputFile = Input.getFile();
+
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
InputFile, CI.getPCHContainerReader(), ASTUnit::LoadPreprocessorOnly,
ASTDiags, CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs);
@@ -604,6 +606,9 @@ bool FrontendAction::BeginSourceFile(Com
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
+ // FIXME: What if the input is a memory buffer?
+ StringRef InputFile = Input.getFile();
+
std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromASTFile(
InputFile, CI.getPCHContainerReader(), ASTUnit::LoadEverything, Diags,
CI.getFileSystemOpts(), CI.getCodeGenOpts().DebugTypeExtRefs);
@@ -791,7 +796,7 @@ bool FrontendAction::BeginSourceFile(Com
// For preprocessed files, check if the first line specifies the original
// source file name with a linemarker.
- std::string PresumedInputFile = InputFile;
+ std::string PresumedInputFile = getCurrentFileOrBufferName();
if (Input.isPreprocessed())
ReadOriginalFileName(CI, PresumedInputFile);
Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Fri Sep 14 18:21:15 2018
@@ -242,6 +242,76 @@ GenerateModuleInterfaceAction::CreateOut
return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
}
+bool GenerateHeaderModuleAction::PrepareToExecuteAction(
+ CompilerInstance &CI) {
+ if (!CI.getLangOpts().Modules && !CI.getLangOpts().ModulesTS) {
+ CI.getDiagnostics().Report(diag::err_header_module_requires_modules);
+ return false;
+ }
+
+ auto &Inputs = CI.getFrontendOpts().Inputs;
+ if (Inputs.empty())
+ return GenerateModuleAction::BeginInvocation(CI);
+
+ auto Kind = Inputs[0].getKind();
+
+ // Convert the header file inputs into a single module input buffer.
+ SmallString<256> HeaderContents;
+ ModuleHeaders.reserve(Inputs.size());
+ for (const FrontendInputFile &FIF : Inputs) {
+ // FIXME: We should support re-compiling from an AST file.
+ if (FIF.getKind().getFormat() != InputKind::Source || !FIF.isFile()) {
+ CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
+ << (FIF.isFile() ? FIF.getFile()
+ : FIF.getBuffer()->getBufferIdentifier());
+ return true;
+ }
+
+ HeaderContents += "#include \"";
+ HeaderContents += FIF.getFile();
+ HeaderContents += "\"\n";
+ ModuleHeaders.push_back(FIF.getFile());
+ }
+ Buffer = llvm::MemoryBuffer::getMemBufferCopy(
+ HeaderContents, Module::getModuleInputBufferName());
+
+ // Set that buffer up as our "real" input.
+ Inputs.clear();
+ Inputs.push_back(FrontendInputFile(Buffer.get(), Kind, /*IsSystem*/false));
+
+ return GenerateModuleAction::PrepareToExecuteAction(CI);
+}
+
+bool GenerateHeaderModuleAction::BeginSourceFileAction(
+ CompilerInstance &CI) {
+ CI.getLangOpts().setCompilingModule(LangOptions::CMK_HeaderModule);
+
+ // Synthesize a Module object for the given headers.
+ auto &HS = CI.getPreprocessor().getHeaderSearchInfo();
+ SmallVector<Module::Header, 16> Headers;
+ for (StringRef Name : ModuleHeaders) {
+ const DirectoryLookup *CurDir = nullptr;
+ const FileEntry *FE = HS.LookupFile(
+ Name, SourceLocation(), /*Angled*/ false, nullptr, CurDir,
+ None, nullptr, nullptr, nullptr, nullptr, nullptr);
+ if (!FE) {
+ CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
+ << Name;
+ continue;
+ }
+ Headers.push_back({Name, FE});
+ }
+ HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers);
+
+ return GenerateModuleAction::BeginSourceFileAction(CI);
+}
+
+std::unique_ptr<raw_pwrite_stream>
+GenerateHeaderModuleAction::CreateOutputFile(CompilerInstance &CI,
+ StringRef InFile) {
+ return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
+}
+
SyntaxOnlyAction::~SyntaxOnlyAction() {
}
Modified: cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp (original)
+++ cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp Fri Sep 14 18:21:15 2018
@@ -61,6 +61,8 @@ CreateFrontendBaseAction(CompilerInstanc
return llvm::make_unique<GenerateModuleFromModuleMapAction>();
case GenerateModuleInterface:
return llvm::make_unique<GenerateModuleInterfaceAction>();
+ case GenerateHeaderModule:
+ return llvm::make_unique<GenerateHeaderModuleAction>();
case GeneratePCH: return llvm::make_unique<GeneratePCHAction>();
case GeneratePTH: return llvm::make_unique<GeneratePTHAction>();
case InitOnly: return llvm::make_unique<InitOnlyAction>();
Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Fri Sep 14 18:21:15 2018
@@ -806,12 +806,11 @@ std::pair<Module *, bool> ModuleMap::fin
}
Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
- assert(!PendingGlobalModule && "created multiple global modules");
- PendingGlobalModule.reset(
+ PendingSubmodules.emplace_back(
new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
/*IsExplicit*/ true, NumCreatedModules++));
- PendingGlobalModule->Kind = Module::GlobalModuleFragment;
- return PendingGlobalModule.get();
+ PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
+ return PendingSubmodules.back().get();
}
Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
@@ -827,10 +826,11 @@ Module *ModuleMap::createModuleForInterf
Modules[Name] = SourceModule = Result;
// Reparent the current global module fragment as a submodule of this module.
- assert(GlobalModule == PendingGlobalModule.get() &&
- "unexpected global module");
- GlobalModule->setParent(Result);
- PendingGlobalModule.release(); // now owned by parent
+ for (auto &Submodule : PendingSubmodules) {
+ Submodule->setParent(Result);
+ Submodule.release(); // now owned by parent
+ }
+ PendingSubmodules.clear();
// Mark the main source file as being within the newly-created module so that
// declarations and macros are properly visibility-restricted to it.
@@ -840,6 +840,29 @@ Module *ModuleMap::createModuleForInterf
return Result;
}
+
+Module *ModuleMap::createHeaderModule(StringRef Name,
+ ArrayRef<Module::Header> Headers) {
+ assert(LangOpts.CurrentModule == Name && "module name mismatch");
+ assert(!Modules[Name] && "redefining existing module");
+
+ auto *Result =
+ new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
+ /*IsExplicit*/ false, NumCreatedModules++);
+ Result->Kind = Module::ModuleInterfaceUnit;
+ Modules[Name] = SourceModule = Result;
+
+ for (const Module::Header &H : Headers) {
+ auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
+ /*IsFramework*/ false,
+ /*IsExplicit*/ true, NumCreatedModules++);
+ // Header modules are implicitly 'export *'.
+ M->Exports.push_back(Module::ExportDecl(nullptr, true));
+ addHeader(M, H, NormalHeader);
+ }
+
+ return Result;
+}
/// For a framework module, infer the framework against which we
/// should link.
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Sep 14 18:21:15 2018
@@ -977,7 +977,8 @@ void Sema::ActOnEndOfTranslationUnit() {
// module declaration by now.
if (getLangOpts().getCompilingModule() ==
LangOptions::CMK_ModuleInterface &&
- ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit) {
+ (ModuleScopes.empty() ||
+ ModuleScopes.back().Module->Kind != Module::ModuleInterfaceUnit)) {
// FIXME: Make a better guess as to where to put the module declaration.
Diag(getSourceManager().getLocForStartOfFile(
getSourceManager().getMainFileID()),
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=342304&r1=342303&r2=342304&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Sep 14 18:21:15 2018
@@ -16832,6 +16832,10 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDe
case LangOptions::CMK_ModuleMap:
Diag(ModuleLoc, diag::err_module_decl_in_module_map_module);
return nullptr;
+
+ case LangOptions::CMK_HeaderModule:
+ Diag(ModuleLoc, diag::err_module_decl_in_header_module);
+ return nullptr;
}
assert(ModuleScopes.size() == 1 && "expected to be at global module scope");
@@ -16900,7 +16904,8 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDe
case ModuleDeclKind::Implementation:
std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc(
PP.getIdentifierInfo(ModuleName), Path[0].second);
- Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible,
+ Mod = getModuleLoader().loadModule(ModuleLoc, {ModuleNameLoc},
+ Module::AllVisible,
/*IsIncludeDirective=*/false);
if (!Mod) {
Diag(ModuleLoc, diag::err_module_not_defined) << ModuleName;
@@ -16930,6 +16935,19 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDe
DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
SourceLocation ImportLoc,
ModuleIdPath Path) {
+ // Flatten the module path for a Modules TS module name.
+ std::pair<IdentifierInfo *, SourceLocation> ModuleNameLoc;
+ if (getLangOpts().ModulesTS) {
+ std::string ModuleName;
+ for (auto &Piece : Path) {
+ if (!ModuleName.empty())
+ ModuleName += ".";
+ ModuleName += Piece.first->getName();
+ }
+ ModuleNameLoc = {PP.getIdentifierInfo(ModuleName), Path[0].second};
+ Path = ModuleIdPath(ModuleNameLoc);
+ }
+
Module *Mod =
getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
/*IsIncludeDirective=*/false);
Added: cfe/trunk/test/Modules/Inputs/no-module-map/a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/no-module-map/a.h?rev=342304&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/no-module-map/a.h (added)
+++ cfe/trunk/test/Modules/Inputs/no-module-map/a.h Fri Sep 14 18:21:15 2018
@@ -0,0 +1,4 @@
+#ifndef A_H
+#define A_H
+void a();
+#endif
Added: cfe/trunk/test/Modules/Inputs/no-module-map/b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/no-module-map/b.h?rev=342304&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/no-module-map/b.h (added)
+++ cfe/trunk/test/Modules/Inputs/no-module-map/b.h Fri Sep 14 18:21:15 2018
@@ -0,0 +1,5 @@
+#ifndef B_H
+#define B_H
+#include "a.h"
+void b();
+#endif
Added: cfe/trunk/test/Modules/no-module-map.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/no-module-map.cpp?rev=342304&view=auto
==============================================================================
--- cfe/trunk/test/Modules/no-module-map.cpp (added)
+++ cfe/trunk/test/Modules/no-module-map.cpp Fri Sep 14 18:21:15 2018
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -fmodules-ts -fmodule-name=ab -x c++-header %S/Inputs/no-module-map/a.h %S/Inputs/no-module-map/b.h -emit-header-module -o %t.pcm
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DA
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DB
+// RUN: %clang_cc1 -fmodules-ts -fmodule-file=%t.pcm %s -I%S/Inputs/no-module-map -verify -DA -DB
+
+#ifdef B
+// expected-no-diagnostics
+#endif
+
+#ifdef A
+#include "a.h"
+#endif
+
+#ifdef B
+#include "b.h"
+#endif
+
+#if defined(A) || defined(B)
+#ifndef A_H
+#error A_H should be defined
+#endif
+#else
+#ifdef A_H
+#error A_H should not be defined
+#endif
+// expected-error at +3 {{must be imported from}}
+// expected-note@* {{previous declaration}}
+#endif
+void use_a() { a(); }
+
+#if defined(B)
+#ifndef B_H
+#error B_H should be defined
+#endif
+#else
+#ifdef B_H
+#error B_H should not be defined
+#endif
+// expected-error at +3 {{must be imported from}}
+// expected-note@* {{previous declaration}}
+#endif
+void use_b() { b(); }
More information about the cfe-commits
mailing list