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
