Author: bruno Date: Thu Dec 21 21:04:43 2017 New Revision: 321342 URL: http://llvm.org/viewvc/llvm-project?rev=321342&view=rev Log: [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 Added: cfe/trunk/test/Modules/implicit-map-dot-private.m Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td cfe/trunk/lib/Frontend/CompilerInstance.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=321342&r1=321341&r2=321342&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Thu Dec 21 21:04:43 2017 @@ -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">; Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=321342&r1=321341&r2=321342&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original) +++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Thu Dec 21 21:04:43 2017 @@ -1854,6 +1854,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) { for (unsigned I = 1, N = Path.size(); I != N; ++I) { StringRef Name = Path[I].first->getName(); @@ -1892,7 +1893,40 @@ CompilerInstance::loadModule(SourceLocat 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(SourceLocat // 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 Added: cfe/trunk/test/Modules/implicit-map-dot-private.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/implicit-map-dot-private.m?rev=321342&view=auto ============================================================================== --- cfe/trunk/test/Modules/implicit-map-dot-private.m (added) +++ cfe/trunk/test/Modules/implicit-map-dot-private.m Thu Dec 21 21:04:43 2017 @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits