From: David Blaikie Date: Tue, 7 May 2019 21:38:51 +0000 (+0000) Subject: -frewrite-imports: Add support for wildcard rules in umbrella modules with X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3bfe0e35eb5cde1d941e3f4fcd6463b80f31e36b;p=clang -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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@360195 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index d632fe095c..0f2549f099 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -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. diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index b405ab621d..f394f26e55 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -321,6 +321,21 @@ Module *Module::findSubmodule(StringRef Name) const { return SubModules[Pos->getValue()]; } +Module *Module::findOrInferSubmodule(StringRef Name) { + llvm::StringMap::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 &Exported) const { // All non-explicit submodules are exported. for (std::vector::const_iterator I = SubModules.begin(), diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index ba1b73e7f4..8aff163d79 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -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; diff --git a/test/Modules/preprocess-umbrella.cpp b/test/Modules/preprocess-umbrella.cpp new file mode 100644 index 0000000000..5d2b86e1c3 --- /dev/null +++ b/test/Modules/preprocess-umbrella.cpp @@ -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'}} +}