diff options
29 files changed, 216 insertions, 87 deletions
diff --git a/docs/Modules.rst b/docs/Modules.rst index 757be61913..2fa38be6f4 100644 --- a/docs/Modules.rst +++ b/docs/Modules.rst @@ -859,10 +859,12 @@ express this with a single module map file in the library: module Foo { header "Foo.h" - - explicit module Private { - header "Foo_Private.h" - } + ... + } + + module Foo_Private { + header "Foo_Private.h" + ... } @@ -873,7 +875,7 @@ build machinery. Private module map files, which are named ``module.private.modulemap`` (or, for backward compatibility, ``module_private.map``), allow one to -augment the primary module map file with an additional submodule. For +augment the primary module map file with an additional modules. For example, we would split the module map file above into two module map files: @@ -883,9 +885,9 @@ files: module Foo { header "Foo.h" } - + /* module.private.modulemap */ - explicit module Foo.Private { + module Foo_Private { header "Foo_Private.h" } @@ -899,13 +901,12 @@ boundaries. When writing a private module as part of a *framework*, it's recommended that: -* Headers for this module are present in the ``PrivateHeaders`` - framework subdirectory. -* The private module is defined as a *submodule* of the public framework (if - there's one), similar to how ``Foo.Private`` is defined in the example above. -* The ``explicit`` keyword should be used to guarantee that its content will - only be available when the submodule itself is explicitly named (through a - ``@import`` for example). +* Headers for this module are present in the ``PrivateHeaders`` framework + subdirectory. +* The private module is defined as a *top level module* with the name of the + public framework prefixed, like ``Foo_Private`` above. Clang has extra logic + to work with this naming, using ``FooPrivate`` or ``Foo.Private`` (submodule) + trigger warnings and might not work as expected. Modularizing a Platform ======================= diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index c664281ffc..c391470cb1 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -691,11 +691,15 @@ def err_mmap_expected_feature : Error<"expected a feature name">; def err_mmap_expected_attribute : Error<"expected an attribute name">; def warn_mmap_unknown_attribute : Warning<"unknown attribute '%0'">, InGroup<IgnoredAttributes>; -def warn_mmap_mismatched_top_level_private : Warning< - "top-level module '%0' in private module map, expected a submodule of '%1'">, +def warn_mmap_mismatched_private_submodule : Warning< + "private submodule '%0' in private module map, expected top-level module">, InGroup<PrivateModule>; -def note_mmap_rename_top_level_private_as_submodule : Note< - "make '%0' a submodule of '%1' to ensure it can be found by name">; +def warn_mmap_mismatched_private_module_name : Warning< + "expected canonical name for private module '%0'">, + InGroup<PrivateModule>; +def note_mmap_rename_top_level_private_module : Note< + "rename '%0' to ensure it can be found by name">; + def err_mmap_duplicate_header_attribute : Error< "header attribute '%0' specified multiple times">; def err_mmap_invalid_header_attribute_value : Error< diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp index aa2588659d..6976294a2e 100644 --- a/lib/Lex/HeaderSearch.cpp +++ b/lib/Lex/HeaderSearch.cpp @@ -209,11 +209,14 @@ Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) { // The facility for "private modules" -- adjacent, optional module maps named // module.private.modulemap that are supposed to define private submodules -- - // is sometimes misused by frameworks that name their associated private - // module FooPrivate, rather than as a submodule named Foo.Private as - // intended. Here we compensate for such cases by looking in directories named - // Foo.framework, when we previously looked and failed to find a - // FooPrivate.framework. + // may have different flavors of names: FooPrivate, Foo_Private and Foo.Private. + // + // Foo.Private is now depracated in favor of Foo_Private. Users of FooPrivate + // should also rename to Foo_Private. Representing private as submodules + // could force building unwanted dependencies into the parent module and cause + // dependency cycles. + if (!Module && SearchName.consume_back("_Private")) + Module = lookupModule(ModuleName, SearchName); if (!Module && SearchName.consume_back("Private")) Module = lookupModule(ModuleName, SearchName); return Module; diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index fbbae7a095..b3ac10c5c5 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -1608,6 +1608,54 @@ namespace { } // namespace +/// Private modules are canonicalized as Foo_Private. Clang provides extra +/// module map search logic to find the appropriate private module when PCH +/// is used with implicit module maps. Warn when private modules are written +/// in other ways (FooPrivate and Foo.Private), providing notes and fixits. +static void diagnosePrivateModules(const ModuleMap &Map, + DiagnosticsEngine &Diags, + const Module *ActiveModule) { + + auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, + const Module *M) { + auto D = Diags.Report(ActiveModule->DefinitionLoc, + diag::note_mmap_rename_top_level_private_module); + D << BadName << M->Name; + D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, Canonical); + }; + + for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { + auto const *M = E->getValue(); + if (M->Directory != ActiveModule->Directory) + continue; + + SmallString<128> FullName(ActiveModule->getFullModuleName()); + if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) + continue; + SmallString<128> Canonical(M->Name); + Canonical.append("_Private"); + + // Foo.Private -> Foo_Private + if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && + M->Name == ActiveModule->Parent->Name) { + Diags.Report(ActiveModule->DefinitionLoc, + diag::warn_mmap_mismatched_private_submodule) + << FullName; + GenNoteAndFixIt(FullName, Canonical, M); + continue; + } + + // FooPrivate and whatnots -> Foo_Private + if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && + ActiveModule->Name != Canonical) { + Diags.Report(ActiveModule->DefinitionLoc, + diag::warn_mmap_mismatched_private_module_name) + << ActiveModule->Name; + GenNoteAndFixIt(ActiveModule->Name, Canonical, M); + } + } +} + /// \brief Parse a module declaration. /// /// module-declaration: @@ -1791,41 +1839,21 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule->NoUndeclaredIncludes = true; ActiveModule->Directory = Directory; - if (!ActiveModule->Parent) { - StringRef MapFileName(ModuleMapFile->getName()); - if (MapFileName.endswith("module.private.modulemap") || - MapFileName.endswith("module_private.map")) { - // Adding a top-level module from a private modulemap is likely a - // user error; we check to see if there's another top-level module - // defined in the non-private map in the same dir, and if so emit a - // warning. - for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { - auto const *M = E->getValue(); - if (!M->Parent && - M->Directory == ActiveModule->Directory && - M->Name != ActiveModule->Name) { - Diags.Report(ActiveModule->DefinitionLoc, - diag::warn_mmap_mismatched_top_level_private) - << ActiveModule->Name << M->Name; - // The pattern we're defending against here is typically due to - // a module named FooPrivate which is supposed to be a submodule - // called Foo.Private. Emit a fixit in that case. - auto D = - Diags.Report(ActiveModule->DefinitionLoc, - diag::note_mmap_rename_top_level_private_as_submodule); - D << ActiveModule->Name << M->Name; - StringRef Bad(ActiveModule->Name); - if (Bad.consume_back("Private")) { - SmallString<128> Fixed = Bad; - Fixed.append(".Private"); - D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, - Fixed); - } - break; - } - } - } - } + + // Private modules named as FooPrivate, Foo.Private or similar are likely a + // user error; provide warnings, notes and fixits to direct users to use + // Foo_Private instead. + SourceLocation StartLoc = + SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); + StringRef MapFileName(ModuleMapFile->getName()); + if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && + !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, + StartLoc) && + !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, + StartLoc) && + (MapFileName.endswith("module.private.modulemap") || + MapFileName.endswith("module_private.map"))) + diagnosePrivateModules(Map, Diags, ActiveModule); bool Done = false; do { diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/a.h b/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/a.h new file mode 100644 index 0000000000..8b4b198745 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/a.h @@ -0,0 +1 @@ +extern int APUBLIC; diff --git a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h b/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/aprivate.h index 760d901aa3..760d901aa3 100644 --- a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/Headers/aprivate.h +++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Headers/aprivate.h diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap new file mode 100644 index 0000000000..95eabf90a9 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +framework module A { + header "a.h" + export * +} diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000..a7606f9c14 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/Modules/module.private.modulemap @@ -0,0 +1,4 @@ +framework module A_Private { + header "aprivate.h" + export * +} diff --git a/test/Modules/Inputs/implicit-private-canonical/A.framework/PrivateHeaders/aprivate.h b/test/Modules/Inputs/implicit-private-canonical/A.framework/PrivateHeaders/aprivate.h new file mode 100644 index 0000000000..760d901aa3 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-canonical/A.framework/PrivateHeaders/aprivate.h @@ -0,0 +1 @@ +extern int APRIVATE; diff --git a/test/Modules/Inputs/implicit-private-with-different-name/A.framework/PrivateHeaders/aprivate.h b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/PrivateHeaders/aprivate.h new file mode 100644 index 0000000000..760d901aa3 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-with-different-name/A.framework/PrivateHeaders/aprivate.h @@ -0,0 +1 @@ +extern int APRIVATE; diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/a.h b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/a.h new file mode 100644 index 0000000000..8b4b198745 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/a.h @@ -0,0 +1 @@ +extern int APUBLIC; diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/aprivate.h b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/aprivate.h new file mode 100644 index 0000000000..760d901aa3 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Headers/aprivate.h @@ -0,0 +1 @@ +extern int APRIVATE; diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap new file mode 100644 index 0000000000..95eabf90a9 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.modulemap @@ -0,0 +1,4 @@ +framework module A { + header "a.h" + export * +} diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap new file mode 100644 index 0000000000..40182969f4 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap @@ -0,0 +1,4 @@ +framework module A.Private { + header "aprivate.h" + export * +} diff --git a/test/Modules/Inputs/implicit-private-with-submodule/A.framework/PrivateHeaders/aprivate.h b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/PrivateHeaders/aprivate.h new file mode 100644 index 0000000000..760d901aa3 --- /dev/null +++ b/test/Modules/Inputs/implicit-private-with-submodule/A.framework/PrivateHeaders/aprivate.h @@ -0,0 +1 @@ +extern int APRIVATE; diff --git a/test/Modules/add-remove-private.m b/test/Modules/add-remove-private.m index dc73a096c8..5e7a5a966a 100644 --- a/test/Modules/add-remove-private.m +++ b/test/Modules/add-remove-private.m @@ -4,7 +4,7 @@ // RUN: cp -r %S/Inputs/AddRemovePrivate.framework %t/AddRemovePrivate.framework // Build with module.private.modulemap -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash -F %t %s -verify -DP +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash -F %t %s -verify -DP -Wno-private-module // RUN: cp %t.mcp/AddRemovePrivate.pcm %t/with.pcm // Build without module.private.modulemap @@ -17,7 +17,7 @@ // Build with module.private.modulemap (again) // RUN: cp %S/Inputs/AddRemovePrivate.framework/Modules/module.private.modulemap %t/AddRemovePrivate.framework/Modules/module.private.modulemap -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash -F %t %s -verify -DP +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t.mcp -fdisable-module-hash -F %t %s -verify -DP -Wno-private-module // RUN: not diff %t.mcp/AddRemovePrivate.pcm %t/without.pcm // expected-no-diagnostics diff --git a/test/Modules/auto-module-import.m b/test/Modules/auto-module-import.m index 9a34c92eab..f6127adcbd 100644 --- a/test/Modules/auto-module-import.m +++ b/test/Modules/auto-module-import.m @@ -1,7 +1,7 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -DERRORS -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -xobjective-c++ %s -verify +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -DERRORS +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -xobjective-c++ %s -verify // // Test both with and without the declarations that refer to unimported // entities. For error recovery, those cases implicitly trigger an import. diff --git a/test/Modules/global_index.m b/test/Modules/global_index.m index 64a70f2a43..e94c69ac3c 100644 --- a/test/Modules/global_index.m +++ b/test/Modules/global_index.m @@ -1,12 +1,12 @@ // RUN: rm -rf %t // Run without global module index -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -fno-modules-global-index -F %S/Inputs %s -verify +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -fno-modules-global-index -F %S/Inputs %s -verify // RUN: ls %t|not grep modules.idx // Run and create the global module index -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify // RUN: ls %t|grep modules.idx // Run and use the global module index -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -print-stats 2>&1 | FileCheck %s +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fdisable-module-hash -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -print-stats 2>&1 | FileCheck %s // expected-no-diagnostics @import DependsOnModule; diff --git a/test/Modules/implicit-private-canonical.m b/test/Modules/implicit-private-canonical.m new file mode 100644 index 0000000000..96b6c4a346 --- /dev/null +++ b/test/Modules/implicit-private-canonical.m @@ -0,0 +1,35 @@ +// RUN: rm -rf %t +// Build PCH using A, with adjacent private module APrivate, which winds up being implicitly referenced +// 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 -DNO_AT_IMPORT +// Use the PCH with no explicit way to resolve APrivate, still pick it up by automatic second-chance search for "A" with "Private" appended +// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -include-pch %t-A.pch %s -fsyntax-only -Wprivate-module -DNO_AT_IMPORT + +// 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 -DUSE_AT_IMPORT_PRIV +// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -include-pch %t-A.pch %s -fsyntax-only -Wprivate-module -DUSE_AT_IMPORT_PRIV + +// 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 -DUSE_AT_IMPORT_BOTH +// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-canonical -include-pch %t-A.pch %s -fsyntax-only -Wprivate-module -DUSE_AT_IMPORT_BOTH + +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +#ifdef NO_AT_IMPORT +#import "A/aprivate.h" +#endif + +#ifdef USE_AT_IMPORT_PRIV +@import A_Private; +#endif + +#ifdef USE_AT_IMPORT_BOTH +@import A; +@import A_Private; +#endif + +const int *y = &APRIVATE; + +#endif diff --git a/test/Modules/implicit-private-with-different-name.m b/test/Modules/implicit-private-with-different-name.m index c09d3979c3..7ee84539bf 100644 --- a/test/Modules/implicit-private-with-different-name.m +++ b/test/Modules/implicit-private-with-different-name.m @@ -1,17 +1,17 @@ // RUN: rm -rf %t // Build PCH using A, with adjacent private module APrivate, which winds up being implicitly referenced -// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -emit-pch -o %t-A.pch %s +// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -emit-pch -o %t-A.pch %s -Wprivate-module // Use the PCH with no explicit way to resolve APrivate, still pick it up by automatic second-chance search for "A" with "Private" appended -// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only +// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only -Wprivate-module // Check the fixit -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-different-name -include-pch %t-A.pch %s -fsyntax-only -fdiagnostics-parseable-fixits -Wprivate-module %s 2>&1 | FileCheck %s -// expected-warning@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{top-level module 'APrivate' in private module map, expected a submodule of 'A'}} -// expected-note@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{make 'APrivate' a submodule of 'A' to ensure it can be found by name}} -// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:18-1:26}:"A.Private" +// expected-warning@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{expected canonical name for private module 'APrivate'}} +// expected-note@Inputs/implicit-private-with-different-name/A.framework/Modules/module.private.modulemap:1{{rename 'APrivate' to ensure it can be found by name}} +// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:18-1:26}:"A_Private" #ifndef HEADER #define HEADER diff --git a/test/Modules/implicit-private-with-submodule.m b/test/Modules/implicit-private-with-submodule.m new file mode 100644 index 0000000000..1779341a5f --- /dev/null +++ b/test/Modules/implicit-private-with-submodule.m @@ -0,0 +1,36 @@ +// RUN: rm -rf %t +// Build PCH using A, with private submodule A.Private +// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-submodule -emit-pch -o %t-A.pch %s -DNO_AT_IMPORT + +// RUN: rm -rf %t +// Build PCH using A, with private submodule A.Private, check the fixit +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-submodule -emit-pch -o %t-A.pch %s -fdiagnostics-parseable-fixits -DNO_AT_IMPORT 2>&1 | FileCheck %s + +// RUN: rm -rf %t +// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-submodule -emit-pch -o %t-A.pch %s -DUSE_AT_IMPORT_PRIV +// RUN: rm -rf %t +// RUN: %clang_cc1 -verify -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/implicit-private-with-submodule -emit-pch -o %t-A.pch %s -DUSE_AT_IMPORT_BOTH + +// expected-warning@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:1{{private submodule 'A.Private' in private module map, expected top-level module}} +// expected-note@Inputs/implicit-private-with-submodule/A.framework/Modules/module.private.modulemap:1{{rename 'A.Private' to ensure it can be found by name}} +// CHECK: fix-it:"{{.*}}module.private.modulemap":{1:20-1:27}:"A_Private" + +#ifndef HEADER +#define HEADER + +#ifdef NO_AT_IMPORT +#import "A/aprivate.h" +#endif + +#ifdef USE_AT_IMPORT_PRIV +@import A.Private; +#endif + +#ifdef USE_AT_IMPORT_BOTH +@import A; +@import A.Private; +#endif + +const int *y = &APRIVATE; + +#endif diff --git a/test/Modules/modulemap-locations.m b/test/Modules/modulemap-locations.m index 3c80db582d..c99bb14dc7 100644 --- a/test/Modules/modulemap-locations.m +++ b/test/Modules/modulemap-locations.m @@ -1,5 +1,5 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/ModuleMapLocations/Module_ModuleMap -I %S/Inputs/ModuleMapLocations/Both -F %S/Inputs/ModuleMapLocations -I %S/Inputs/ModuleMapLocations -F %S/Inputs -x objective-c -fsyntax-only %s -verify +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/ModuleMapLocations/Module_ModuleMap -I %S/Inputs/ModuleMapLocations/Both -F %S/Inputs/ModuleMapLocations -I %S/Inputs/ModuleMapLocations -F %S/Inputs -x objective-c -fsyntax-only %s -verify -Wno-private-module // regular @import module_modulemap; diff --git a/test/Modules/prune.m b/test/Modules/prune.m index 58992f9c00..97a2fd7d0d 100644 --- a/test/Modules/prune.m +++ b/test/Modules/prune.m @@ -8,8 +8,8 @@ // Clear out the module cache // RUN: rm -rf %t // Run Clang twice so we end up creating the timestamp file (the second time). -// RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t %s -verify -// RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t %s -verify +// RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -Wno-private-module -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t %s -verify +// RUN: %clang_cc1 -DIMPORT_DEPENDS_ON_MODULE -Wno-private-module -fmodules-ignore-macro=DIMPORT_DEPENDS_ON_MODULE -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t %s -verify // RUN: ls %t | grep modules.timestamp // RUN: ls -R %t | grep ^Module.*pcm // RUN: ls -R %t | grep DependsOnModule.*pcm @@ -17,7 +17,7 @@ // Set the timestamp back more than two days. We should try to prune, // but nothing gets pruned because the module files are new enough. // RUN: touch -m -a -t 201101010000 %t/modules.timestamp -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -Wno-private-module -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify // RUN: ls %t | grep modules.timestamp // RUN: ls -R %t | grep ^Module.*pcm // RUN: ls -R %t | grep DependsOnModule.*pcm @@ -26,7 +26,7 @@ // This shouldn't prune anything, because the timestamp has been updated, so // the pruning mechanism won't fire. // RUN: find %t -name DependsOnModule*.pcm | sed -e 's/\\/\//g' | xargs touch -a -t 201101010000 -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -Wno-private-module -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify // RUN: ls %t | grep modules.timestamp // RUN: ls -R %t | grep ^Module.*pcm // RUN: ls -R %t | grep DependsOnModule.*pcm @@ -35,7 +35,7 @@ // This should trigger pruning, which will remove DependsOnModule but not Module. // RUN: touch -m -a -t 201101010000 %t/modules.timestamp // RUN: find %t -name DependsOnModule*.pcm | sed -e 's/\\/\//g' | xargs touch -a -t 201101010000 -// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify +// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -F %S/Inputs -Wno-private-module -fmodules-cache-path=%t -fmodules -fmodules-prune-interval=172800 -fmodules-prune-after=345600 %s -verify // RUN: ls %t | grep modules.timestamp // RUN: ls -R %t | grep ^Module.*pcm // RUN: ls -R %t | not grep DependsOnModule.*pcm diff --git a/test/Modules/redefinition-c-tagtypes.m b/test/Modules/redefinition-c-tagtypes.m index a01f11bd74..eb469e00e1 100644 --- a/test/Modules/redefinition-c-tagtypes.m +++ b/test/Modules/redefinition-c-tagtypes.m @@ -1,8 +1,8 @@ // RUN: rm -rf %t.cache // RUN: %clang_cc1 -fsyntax-only %s -fmodules -fmodules-cache-path=%t.cache \ -// RUN: -fimplicit-module-maps -F%S/Inputs -verify +// RUN: -fimplicit-module-maps -Wno-private-module -F%S/Inputs -verify // RUN: %clang_cc1 -fsyntax-only %s -fmodules -fmodules-cache-path=%t.cache \ -// RUN: -fimplicit-module-maps -F%S/Inputs -DCHANGE_TAGS -verify +// RUN: -fimplicit-module-maps -Wno-private-module -F%S/Inputs -DCHANGE_TAGS -verify #include "F/F.h" #ifndef CHANGE_TAGS diff --git a/test/Modules/requires-coroutines.mm b/test/Modules/requires-coroutines.mm index 8e25a3c575..4e9c9d19cd 100644 --- a/test/Modules/requires-coroutines.mm +++ b/test/Modules/requires-coroutines.mm @@ -1,6 +1,6 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify -// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify -fcoroutines-ts -DCOROUTINES +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -Wno-private-module -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify +// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -Wno-private-module -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify -fcoroutines-ts -DCOROUTINES #ifdef COROUTINES @import DependsOnModule.Coroutines; diff --git a/test/Modules/requires.m b/test/Modules/requires.m index d61de6bd48..4a83d0c2b0 100644 --- a/test/Modules/requires.m +++ b/test/Modules/requires.m @@ -1,5 +1,5 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs %s -verify -fmodule-feature custom_req1 +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs %s -verify -fmodule-feature custom_req1 // expected-error@DependsOnModule.framework/module.map:7 {{module 'DependsOnModule.CXX' requires feature 'cplusplus'}} @import DependsOnModule.CXX; // expected-note {{module imported here}} diff --git a/test/Modules/requires.mm b/test/Modules/requires.mm index f90622ece8..b4237cbd78 100644 --- a/test/Modules/requires.mm +++ b/test/Modules/requires.mm @@ -1,5 +1,5 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify @import DependsOnModule.CXX; // expected-error@module.map:11 {{module 'DependsOnModule.NotCXX' is incompatible with feature 'cplusplus'}} diff --git a/test/Modules/subframework-from-intermediate-path.m b/test/Modules/subframework-from-intermediate-path.m index 394cc45f2f..1543861ec4 100644 --- a/test/Modules/subframework-from-intermediate-path.m +++ b/test/Modules/subframework-from-intermediate-path.m @@ -1,5 +1,5 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify +// RUN: %clang_cc1 -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify @import DependsOnModule; @import SubFramework; // expected-error{{module 'SubFramework' not found}} diff --git a/test/Modules/subframeworks.m b/test/Modules/subframeworks.m index 21081843d7..ce35415717 100644 --- a/test/Modules/subframeworks.m +++ b/test/Modules/subframeworks.m @@ -1,6 +1,6 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify -// RUN: %clang_cc1 -x objective-c++ -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify +// RUN: %clang_cc1 -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify +// RUN: %clang_cc1 -x objective-c++ -Wauto-import -Wno-private-module -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -F %S/Inputs/DependsOnModule.framework/Frameworks %s -verify @import DependsOnModule; |