summaryrefslogtreecommitdiff
path: root/lib/Lex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lex')
-rw-r--r--lib/Lex/HeaderSearch.cpp13
-rw-r--r--lib/Lex/ModuleMap.cpp98
-rw-r--r--lib/Lex/Preprocessor.cpp7
3 files changed, 74 insertions, 44 deletions
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index aa2588659ddf..6976294a2eaf 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 fbbae7a09520..b3ac10c5c5ae 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/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index c291a4b99d10..7d789e780113 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -420,10 +420,9 @@ bool Preprocessor::SetCodeCompletionPoint(const FileEntry *File,
CodeCompletionFile = File;
CodeCompletionOffset = Position - Buffer->getBufferStart();
- std::unique_ptr<MemoryBuffer> NewBuffer =
- MemoryBuffer::getNewUninitMemBuffer(Buffer->getBufferSize() + 1,
- Buffer->getBufferIdentifier());
- char *NewBuf = const_cast<char*>(NewBuffer->getBufferStart());
+ auto NewBuffer = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
+ Buffer->getBufferSize() + 1, Buffer->getBufferIdentifier());
+ char *NewBuf = NewBuffer->getBufferStart();
char *NewPos = std::copy(Buffer->getBufferStart(), Position, NewBuf);
*NewPos = '\0';
std::copy(Position, Buffer->getBufferEnd(), NewPos+1);