-frewrite-imports: Add support for wildcard rules in umbrella modules with

This trips over a few other limitations, but in the interests of incremental development I'm starting here & I'll look at the issues with -verify and filesystem checks (the fact that the behavior depends on the existence of a 'foo' directory even though it shouldn't need it), etc.

Reviewers: rsmith

Differential Revision: https://reviews.llvm.org/D61656

llvm-svn: 360195
This commit is contained in:
David Blaikie 2019-05-07 21:38:51 +00:00
parent 2b09b25e48
commit 89e58ddb28
4 changed files with 55 additions and 4 deletions

View File

@ -541,6 +541,7 @@ public:
///
/// \returns The submodule if found, or NULL otherwise.
Module *findSubmodule(StringRef Name) const;
Module *findOrInferSubmodule(StringRef Name);
/// Determine whether the specified module would be visible to
/// a lookup at the end of this module.

View File

@ -321,6 +321,21 @@ Module *Module::findSubmodule(StringRef Name) const {
return SubModules[Pos->getValue()];
}
Module *Module::findOrInferSubmodule(StringRef Name) {
llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
if (Pos != SubModuleIndex.end())
return SubModules[Pos->getValue()];
if (!InferSubmodules)
return nullptr;
Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0);
Result->InferExplicitSubmodules = InferExplicitSubmodules;
Result->InferSubmodules = InferSubmodules;
Result->InferExportWildcard = InferExportWildcard;
if (Result->InferExportWildcard)
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
return Result;
}
void Module::getExportedModules(SmallVectorImpl<Module *> &Exported) const {
// All non-explicit submodules are exported.
for (std::vector<Module *>::const_iterator I = SubModules.begin(),

View File

@ -1584,16 +1584,15 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
// Find the module we're entering. We require that a module map for it
// be loaded or implicitly loadable.
// FIXME: We could create the submodule here. We'd need to know whether
// it's supposed to be explicit, but not much else.
Module *M = PP.getHeaderSearchInfo().lookupModule(Current);
auto &HSI = PP.getHeaderSearchInfo();
Module *M = HSI.lookupModule(Current);
if (!M) {
PP.Diag(ModuleName.front().second,
diag::err_pp_module_begin_no_module_map) << Current;
return;
}
for (unsigned I = 1; I != ModuleName.size(); ++I) {
auto *NewM = M->findSubmodule(ModuleName[I].first->getName());
auto *NewM = M->findOrInferSubmodule(ModuleName[I].first->getName());
if (!NewM) {
PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule)
<< M->getFullModuleName() << ModuleName[I].first;

View File

@ -0,0 +1,36 @@
// FIXME: The standalone module still seems to cause clang to want to test for
// the existence of a 'foo' directory:
// RUN: mkdir %t
// RUN: cp %s %t
// RUN: mkdir %t/foo
// RUN: cd %t
// RUN: not %clang_cc1 -fmodules -fsyntax-only %s 2>&1 | FileCheck %s
// CHECK: error: no matching function for call to 'foo'
// CHECK: note: candidate function not viable: requires 0 arguments, but 1 was provided
// FIXME: This should use -verify, but it seems it doesn't hook up the
// SourceManager correctly or something, and the foo.h note gets attributed to
// the synthetic module translation unit "foo.map Line 2:...".
// %clang_cc1 -fmodules -verify %s
#pragma clang module build foo
module foo {
umbrella "foo"
module * {
export *
}
}
#pragma clang module contents
#pragma clang module begin foo.foo
# 1 "foo.h" 1
#ifndef FOO_FOO_H
void foo();
#endif
#pragma clang module end
#pragma clang module endbuild
#pragma clang module import foo.foo
// expected-note@foo.h:2 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
int main() {
foo(1); // expected-error {{no matching function for call to 'foo'}}
}