mirror of https://github.com/microsoft/clang.git
[Modules] Map missing private submodules from Foo.Private to Foo_Private
In case `@import Foo.Private` fails because the submodule doesn't exist, look for `Foo_Private` (if available) and build/load that module instead. In that process emit a warning and tell the user about the assumption. The intention here is to assist all existing private modules owners (in ObjC and Swift) to migrate to the new `Foo_Private` syntax. rdar://problem/36023940 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321342 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bc87ce76c2
commit
e959732272
|
@ -198,6 +198,11 @@ def err_missing_module : Error<
|
|||
def err_no_submodule : Error<"no submodule named %0 in module '%1'">;
|
||||
def err_no_submodule_suggest : Error<
|
||||
"no submodule named %0 in module '%1'; did you mean '%2'?">;
|
||||
def warn_no_priv_submodule_use_toplevel : Warning<
|
||||
"no submodule named %0 in module '%1'; using top level '%2'">,
|
||||
InGroup<PrivateModule>;
|
||||
def note_private_top_level_defined : Note<
|
||||
"module defined here">;
|
||||
def warn_missing_submodule : Warning<"missing submodule '%0'">,
|
||||
InGroup<IncompleteUmbrella>;
|
||||
def note_module_import_here : Note<"module imported here">;
|
||||
|
|
|
@ -1854,6 +1854,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) {
|
||||
for (unsigned I = 1, N = Path.size(); I != N; ++I) {
|
||||
StringRef Name = Path[I].first->getName();
|
||||
|
@ -1892,7 +1893,40 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
Sub = Module->findSubmodule(Best[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the user is requesting Foo.Private and it doesn't exist, try to
|
||||
// match Foo_Private and emit a warning asking for the user to write
|
||||
// @import Foo_Private instead. FIXME: remove this when existing clients
|
||||
// migrate off of Foo.Private syntax.
|
||||
if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" &&
|
||||
Module == Module->getTopLevelModule()) {
|
||||
SmallString<128> PrivateModule(Module->Name);
|
||||
PrivateModule.append("_Private");
|
||||
|
||||
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath;
|
||||
auto &II = PP->getIdentifierTable().get(
|
||||
PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
|
||||
PrivPath.push_back(std::make_pair(&II, Path[0].second));
|
||||
|
||||
if (PP->getHeaderSearchInfo().lookupModule(PrivateModule))
|
||||
Sub =
|
||||
loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
|
||||
if (Sub) {
|
||||
MapPrivateSubModToTopLevel = true;
|
||||
if (!getDiagnostics().isIgnored(
|
||||
diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) {
|
||||
getDiagnostics().Report(Path[I].second,
|
||||
diag::warn_no_priv_submodule_use_toplevel)
|
||||
<< Path[I].first << Module->getFullModuleName() << PrivateModule
|
||||
<< SourceRange(Path[0].second, Path[I].second)
|
||||
<< FixItHint::CreateReplacement(SourceRange(Path[0].second),
|
||||
PrivateModule);
|
||||
getDiagnostics().Report(Sub->DefinitionLoc,
|
||||
diag::note_private_top_level_defined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Sub) {
|
||||
// No submodule by this name. Complain, and don't look for further
|
||||
// submodules.
|
||||
|
@ -1909,7 +1943,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
// Make the named module visible, if it's not already part of the module
|
||||
// we are parsing.
|
||||
if (ModuleName != getLangOpts().CurrentModule) {
|
||||
if (!Module->IsFromModuleFile) {
|
||||
if (!Module->IsFromModuleFile && !MapPrivateSubModToTopLevel) {
|
||||
// We have an umbrella header or directory that doesn't actually include
|
||||
// all of the headers within the directory it covers. Complain about
|
||||
// this missing submodule and recover by forgetting that we ever saw
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -emit-pch -o %t-A.pch %s -Wprivate-module
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
@import A.Private; // expected-warning {{no submodule named 'Private' in module 'A'; using top level 'A_Private'}}
|
||||
// expected-note@Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap:1{{module defined here}}
|
||||
|
||||
const int *y = &APRIVATE;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue