https://github.com/mikomikotaishi updated 
https://github.com/llvm/llvm-project/pull/187657

>From 6424fa22466d50c21a18d2c27b96a126bc48e3ab Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <[email protected]>
Date: Fri, 20 Mar 2026 03:56:15 -0400
Subject: [PATCH 1/5] 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 4b9b604d27b16..f6bc06b914379 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -4741,7 +4741,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 306f8069c44f0c8983fc0bbb143a7224b5119598 Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <[email protected]>
Date: Sun, 22 Mar 2026 19:19:28 -0400
Subject: [PATCH 2/5] 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 923dff2e98f781ded3974108cbd5825289ba6a18 Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <[email protected]>
Date: Sun, 22 Mar 2026 23:39:40 -0400
Subject: [PATCH 3/5] 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 29236bd0f4782..b431fb8e1d221 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -4226,6 +4226,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 62d67e08e6083..780f7936cd00c 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -1380,7 +1380,7 @@ bool Preprocessor::HandleModuleContextualKeyword(Token 
&Result) {
       if (NextTok->is(tok::raw_identifier))
         LookUpIdentifierInfo(*NextTok);
       if (NextTok->isOneOf(tok::header_name, tok::identifier, tok::colon,
-                           tok::less)) {
+                           tok::less, tok::code_completion)) {
         Result.setKind(tok::kw_import);
         ModuleImportLoc = Result.getLocation();
         return true;

>From ec765f2c58e28c302ec0319f11652f4b79898432 Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <[email protected]>
Date: Mon, 23 Mar 2026 00:50:55 -0400
Subject: [PATCH 4/5] 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 f6bc06b914379..d57ac1dac8000 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"
@@ -4742,6 +4744,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.
@@ -4757,6 +4760,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.

>From 49b71fea7fd72ca9be5fa23d06e604fbeadbabb7 Mon Sep 17 00:00:00 2001
From: Toyosatomimi no Miko <[email protected]>
Date: Sun, 23 Aug 2026 23:58:58 -0400
Subject: [PATCH 5/5] Adapt module import completion to upstream module
 directive processing

Upstream now processes C++20 module declarations as preprocessor
directives, so at the point where an import's module-name completion
fires (also during preprocessing), Sema may not have acted on the
module declaration yet and getCurrentModule() can be null. This made
the partition filter drop the current module's own partitions.

Determine the current primary module interface name from Sema when
available, falling back to the preprocessor's module declaration state
otherwise.

Also split the module declarations in the test inputs onto their own
lines, since everything after ';' in a module directive now triggers
-Wextra-tokens.
---
 clang/lib/Sema/SemaCodeComplete.cpp           | 20 +++++++++++++------
 .../test/CodeCompletion/module-partitions.cpp |  4 ++--
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index d57ac1dac8000..b906a67f4e45e 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -4743,15 +4743,24 @@ void 
SemaCodeCompletion::CodeCompleteModuleImport(SourceLocation ImportLoc,
     // Enumerate all top-level modules.
     SmallVector<Module *, 8> Modules;
     SemaRef.PP.getHeaderSearchInfo().collectAllModules(Modules);
-    Module *CurrentModule = SemaRef.getCurrentModule();
+    // Determine the primary module interface name of the current file's
+    // declared module, if any. Prefer Sema's view, but fall back to the
+    // preprocessor's module declaration state: module declarations are
+    // processed as preprocessor directives, so the preprocessor may know the
+    // declared module before Sema has acted on it (e.g. when completing an
+    // import right after the module declaration).
+    StringRef CurrentPrimary;
+    if (Module *CurrentModule = SemaRef.getCurrentModule())
+      CurrentPrimary = CurrentModule->getPrimaryModuleInterfaceName();
+    else if (SemaRef.PP.isInNamedModule())
+      CurrentPrimary = SemaRef.PP.getNamedModuleName().split(':').first;
     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.
       if (Modules[I]->isModulePartition()) {
-        if (!CurrentModule ||
-            Modules[I]->getPrimaryModuleInterfaceName() !=
-                CurrentModule->getPrimaryModuleInterfaceName())
+        if (CurrentPrimary.empty() ||
+            Modules[I]->getPrimaryModuleInterfaceName() != CurrentPrimary)
           continue;
       }
       Builder.AddTypedTextChunk(
@@ -4773,8 +4782,7 @@ void 
SemaCodeCompletion::CodeCompleteModuleImport(SourceLocation ImportLoc,
       StringRef Name = Entry.first;
       // Apply the same partition filtering as above.
       if (auto [Primary, Partition] = Name.split(':'); !Partition.empty()) {
-        if (!CurrentModule ||
-            Primary != CurrentModule->getPrimaryModuleInterfaceName())
+        if (CurrentPrimary.empty() || Primary != CurrentPrimary)
           continue;
       }
       Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Name));
diff --git a/clang/test/CodeCompletion/module-partitions.cpp 
b/clang/test/CodeCompletion/module-partitions.cpp
index bdbadf6351c8f..698d18eea7f1b 100644
--- a/clang/test/CodeCompletion/module-partitions.cpp
+++ b/clang/test/CodeCompletion/module-partitions.cpp
@@ -1,11 +1,11 @@
 // 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: printf 'export module M:Part;\nexport int mpart_func();\n' > 
%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: printf 'export module N:OtherPart;\nexport int npart_func();\n' > 
%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

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to