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

>From 8e16d5424e5d7df17da6465e318f2c105d8cfa85 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 a9dd2ab514545527c30d5d22db9736ba1dd33872 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 3ff118adecda7b5c1c216a31b88c5a23e0409542 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 ecaf4ac0af4aaf2e1c238300263ae56c5b93db60 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 02f353cb54fb65e8dd87aa59c2f321fd5efe37e9 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