summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-09-15 01:21:15 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-09-15 01:21:15 +0000
commitd6509cf21dd017392f82da0eb9b0345fbfc8970b (patch)
tree2b3223d4aabe04fc1205a9e2158019bd3c87275b /clang/lib
parent66f3dc031d7922cb87b115ce8e5ca38db67aadd2 (diff)
downloadbcm5719-llvm-d6509cf21dd017392f82da0eb9b0345fbfc8970b.tar.gz
bcm5719-llvm-d6509cf21dd017392f82da0eb9b0345fbfc8970b.zip
[modules] Frontend support for building a header module from a list of
headaer files. llvm-svn: 342304
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp22
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp3
-rw-r--r--clang/lib/Frontend/FrontendAction.cpp9
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp70
-rw-r--r--clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp2
-rw-r--r--clang/lib/Lex/ModuleMap.cpp39
-rw-r--r--clang/lib/Sema/Sema.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp20
8 files changed, 139 insertions, 29 deletions
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 38a09a0dac3..05ba3c0265a 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -911,6 +911,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
// 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(SourceLocation ImportLoc,
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(SourceLocation ImportLoc,
// 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);
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index b11581ddf79..55745b19633 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1454,6 +1454,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
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(frontend::ActionKind Action) {
case frontend::FixIt:
case frontend::GenerateModule:
case frontend::GenerateModuleInterface:
+ case frontend::GenerateHeaderModule:
case frontend::GeneratePCH:
case frontend::GeneratePTH:
case frontend::ParseSyntaxOnly:
diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp
index ddb522ae05f..10f1d1ef611 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -523,7 +523,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
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(CompilerInstance &CI,
&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(CompilerInstance &CI,
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(CompilerInstance &CI,
// 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);
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 40008bf3cdd..d0d83076f1d 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -242,6 +242,76 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
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() {
}
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 747fdd24164..4deebcd4777 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -61,6 +61,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
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>();
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index a1e91382175..b6a6e26d6ad 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -806,12 +806,11 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
}
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::createModuleForInterfaceUnit(SourceLocation Loc,
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.
@@ -841,6 +841,29 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
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.
static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 82a04e1070d..4b0e69c7f65 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -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()),
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f1e9286b7ec..eacf713b9d0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -16832,6 +16832,10 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
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::ActOnModuleDecl(SourceLocation StartLoc,
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::ActOnModuleDecl(SourceLocation StartLoc,
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);
OpenPOWER on IntegriCloud