[clang] [Sema] [Modules] Remove unrelated module partitions from suggestion list (PR #187657)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 25 00:06:02 PDT 2026
https://github.com/mikomikotaishi updated https://github.com/llvm/llvm-project/pull/187657
>From 8ac34daf0af6659e04df44aacff5dadf806df8bd Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <110693261+mikomikotaishi at users.noreply.github.com>
Date: Fri, 20 Mar 2026 03:56:15 -0400
Subject: [PATCH 1/4] Remove unrelated module partitions from suggestion list
---
clang/lib/Sema/SemaCodeComplete.cpp | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 0cd9819dc2964..a04e942d2ee28 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -4696,7 +4696,16 @@ void SemaCodeCompletion::CodeCompleteModuleImport(SourceLocation ImportLoc,
// Enumerate all top-level modules.
SmallVector<Module *, 8> Modules;
SemaRef.PP.getHeaderSearchInfo().collectAllModules(Modules);
+ Module *CurrentModule = SemaRef.getCurrentModule();
for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
+ // Skip module partitions that don't belong to the current file's declared
+ // module.
+ if (Modules[I]->isModulePartition()) {
+ if (!CurrentModule ||
+ Modules[I]->getPrimaryModuleInterfaceName() !=
+ CurrentModule->getPrimaryModuleInterfaceName())
+ continue;
+ }
Builder.AddTypedTextChunk(
Builder.getAllocator().CopyString(Modules[I]->Name));
Results.AddResult(Result(
>From 2768ca03645dd106edc1be3aa7d38c3f2fd46015 Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <110693261+mikomikotaishi at users.noreply.github.com>
Date: Sun, 22 Mar 2026 19:19:28 -0400
Subject: [PATCH 2/4] Add a module test for code completion
---
.../test/CodeCompletion/module-partitions.cpp | 26 +++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 clang/test/CodeCompletion/module-partitions.cpp
diff --git a/clang/test/CodeCompletion/module-partitions.cpp b/clang/test/CodeCompletion/module-partitions.cpp
new file mode 100644
index 0000000000000..bdbadf6351c8f
--- /dev/null
+++ b/clang/test/CodeCompletion/module-partitions.cpp
@@ -0,0 +1,26 @@
+// RUN: rm -rf %t && mkdir %t
+
+// Set up a partition of module M.
+// RUN: echo 'export module M:Part; export int mpart_func();' > %t/m-part.cppm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/m-part.cppm -o %t/M-Part.pcm
+
+// Set up module N with a partition.
+// RUN: echo 'export module N:OtherPart; export int npart_func();' > %t/n-otherpart.cppm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/n-otherpart.cppm -o %t/N-OtherPart.pcm
+// RUN: printf 'export module N;\nexport import :OtherPart;\n' > %t/n.cppm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/n.cppm -fmodule-file=N:OtherPart=%t/N-OtherPart.pcm -o %t/N.pcm
+
+// Complete at the module name position in an "import" inside module M.
+// Own partition (M:Part) should be suggested; another module's partition
+// (N:OtherPart) should be filtered out.
+// RUN: %clang_cc1 -std=c++20 -code-completion-at=%s:%(line+6):8 %s \
+// RUN: -fmodule-file=M:Part=%t/M-Part.pcm \
+// RUN: -fmodule-file=N=%t/N.pcm \
+// RUN: -fmodule-file=N:OtherPart=%t/N-OtherPart.pcm | FileCheck %s
+
+export module M;
+import ;
+
+// CHECK-NOT: OtherPart
+// CHECK: M:Part
+// CHECK-NOT: OtherPart
>From e767bbbabdb7860b1bcb45ff0848169cc81a7002 Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <110693261+mikomikotaishi at users.noreply.github.com>
Date: Sun, 22 Mar 2026 23:39:40 -0400
Subject: [PATCH 3/4] Fix unhandled code completion cases in preprocessing
---
clang/lib/Lex/PPDirectives.cpp | 1 +
clang/lib/Lex/Preprocessor.cpp | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index c89402fa137c0..19f2bb34c235a 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -4220,6 +4220,7 @@ void Preprocessor::HandleCXXImportDirective(Token ImportTok) {
UseLoc = Tok.getLocation();
Lex(Tok);
[[fallthrough]];
+ case tok::code_completion:
case tok::identifier: {
if (HandleModuleName(ImportTok.getIdentifierInfo()->getName(), UseLoc, Tok,
Path, DirToks, /*AllowMacroExpansion=*/true,
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 2cfefac1052a4..6358b34dee3ed 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -1354,7 +1354,7 @@ bool Preprocessor::HandleModuleContextualKeyword(Token &Result) {
if (Result.getIdentifierInfo()->isImportKeyword()) {
if (NextTok->isOneOf(tok::identifier, tok::less, tok::colon,
- tok::header_name)) {
+ tok::header_name, tok::code_completion)) {
Result.setKind(tok::kw_import);
ModuleImportLoc = Result.getLocation();
IsAtImport = false;
>From 7cc18e6ac462ac407af8600d2a889787b0bfe69f Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <110693261+mikomikotaishi at users.noreply.github.com>
Date: Mon, 23 Mar 2026 00:50:55 -0400
Subject: [PATCH 4/4] Add prebuilt module files to results
---
clang/lib/Sema/SemaCodeComplete.cpp | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index a04e942d2ee28..08fee5577cf5a 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -30,6 +30,7 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CodeCompleteConsumer.h"
@@ -50,6 +51,7 @@
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/iterator_range.h"
@@ -4697,6 +4699,7 @@ void SemaCodeCompletion::CodeCompleteModuleImport(SourceLocation ImportLoc,
SmallVector<Module *, 8> Modules;
SemaRef.PP.getHeaderSearchInfo().collectAllModules(Modules);
Module *CurrentModule = SemaRef.getCurrentModule();
+ llvm::StringSet<> AddedModules;
for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
// Skip module partitions that don't belong to the current file's declared
// module.
@@ -4712,6 +4715,27 @@ void SemaCodeCompletion::CodeCompleteModuleImport(SourceLocation ImportLoc,
Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
Modules[I]->isAvailable() ? CXAvailability_Available
: CXAvailability_NotAvailable));
+ AddedModules.insert(Modules[I]->Name);
+ }
+
+ // Also suggest C++20 named modules from -fmodule-file=<name>=<path> that
+ // haven't been loaded into the module map yet.
+ for (const auto &Entry : SemaRef.PP.getHeaderSearchInfo()
+ .getHeaderSearchOpts()
+ .PrebuiltModuleFiles) {
+ if (AddedModules.count(Entry.first))
+ continue;
+ StringRef Name = Entry.first;
+ // Apply the same partition filtering as above.
+ if (auto [Primary, Partition] = Name.split(':'); !Partition.empty()) {
+ if (!CurrentModule ||
+ Primary != CurrentModule->getPrimaryModuleInterfaceName())
+ continue;
+ }
+ Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Name));
+ Results.AddResult(Result(Builder.TakeString(), CCP_Declaration,
+ CXCursor_ModuleImportDecl,
+ CXAvailability_Available));
}
} else if (getLangOpts().Modules) {
// Load the named module.
More information about the cfe-commits
mailing list