Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions clang-tools-extra/clangd/ModulesBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ class FailedPrerequisiteModules : public PrerequisiteModules {

// We shouldn't adjust the compilation commands based on
// FailedPrerequisiteModules.
void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override {
}
void adjustHeaderSearchOptions(HeaderSearchOptions &Options) const override {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally we don't like unnecessary changes, if you want, you can make such changes in seperate pacthes.


// FailedPrerequisiteModules can never be reused.
bool
Expand Down Expand Up @@ -430,21 +429,21 @@ class CachingProjectModules : public ProjectModules {
/// Collect the directly and indirectly required module names for \param
/// ModuleName in topological order. The \param ModuleName is guaranteed to
/// be the last element in \param ModuleNames.
llvm::SmallVector<StringRef> getAllRequiredModules(PathRef RequiredSource,
CachingProjectModules &MDB,
StringRef ModuleName) {
llvm::SmallVector<llvm::StringRef> ModuleNames;
llvm::SmallVector<std::string> getAllRequiredModules(PathRef RequiredSource,
CachingProjectModules &MDB,
StringRef ModuleName) {
llvm::SmallVector<std::string> ModuleNames;
llvm::StringSet<> ModuleNamesSet;

auto VisitDeps = [&](StringRef ModuleName, auto Visitor) -> void {
ModuleNamesSet.insert(ModuleName);

for (StringRef RequiredModuleName : MDB.getRequiredModules(
for (const std::string &RequiredModuleName : MDB.getRequiredModules(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be better to use StringRef here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change this back to a StringRef when I resubmit this after the arm64 build issues are resolved.

MDB.getSourceForModuleName(ModuleName, RequiredSource)))
if (ModuleNamesSet.insert(RequiredModuleName).second)
Visitor(RequiredModuleName, Visitor);

ModuleNames.push_back(ModuleName);
ModuleNames.push_back(ModuleName.str());
};
VisitDeps(ModuleName, VisitDeps);

Expand Down Expand Up @@ -494,28 +493,30 @@ llvm::Error ModulesBuilder::ModulesBuilderImpl::getOrBuildModuleFile(
// Get Required modules in topological order.
auto ReqModuleNames = getAllRequiredModules(RequiredSource, MDB, ModuleName);
for (llvm::StringRef ReqModuleName : ReqModuleNames) {
if (BuiltModuleFiles.isModuleUnitBuilt(ModuleName))
if (BuiltModuleFiles.isModuleUnitBuilt(ReqModuleName))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, what a shame. I didn't notice this, my bad.

continue;

if (auto Cached = Cache.getModule(ReqModuleName)) {
if (IsModuleFileUpToDate(Cached->getModuleFilePath(), BuiltModuleFiles,
TFS.view(std::nullopt))) {
log("Reusing module {0} from {1}", ModuleName,
log("Reusing module {0} from {1}", ReqModuleName,
Cached->getModuleFilePath());
BuiltModuleFiles.addModuleFile(std::move(Cached));
continue;
}
Cache.remove(ReqModuleName);
}

std::string ReqFileName =
MDB.getSourceForModuleName(ReqModuleName, RequiredSource);
llvm::Expected<ModuleFile> MF = buildModuleFile(
ModuleName, ModuleUnitFileName, getCDB(), TFS, BuiltModuleFiles);
ReqModuleName, ReqFileName, getCDB(), TFS, BuiltModuleFiles);
if (llvm::Error Err = MF.takeError())
return Err;

log("Built module {0} to {1}", ModuleName, MF->getModuleFilePath());
log("Built module {0} to {1}", ReqModuleName, MF->getModuleFilePath());
auto BuiltModuleFile = std::make_shared<const ModuleFile>(std::move(*MF));
Cache.add(ModuleName, BuiltModuleFile);
Cache.add(ReqModuleName, BuiltModuleFile);
BuiltModuleFiles.addModuleFile(std::move(BuiltModuleFile));
}

Expand Down
92 changes: 92 additions & 0 deletions clang-tools-extra/clangd/test/module_dependencies.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# A smoke test to check that a simple dependency chain for modules can work.
#
# RUN: rm -fr %t
# RUN: mkdir -p %t
# RUN: split-file %s %t
#
# RUN: sed -e "s|DIR|%/t|g" %t/compile_commands.json.tmpl > %t/compile_commands.json.tmp
# RUN: sed -e "s|CLANG_CC|%clang|g" %t/compile_commands.json.tmp > %t/compile_commands.json
# RUN: sed -e "s|DIR|%/t|g" %t/definition.jsonrpc.tmpl > %t/definition.jsonrpc.tmp
#
# On Windows, we need the URI in didOpen to look like "uri":"file:///C:/..."
# (with the extra slash in the front), so we add it here.
# RUN: sed -E -e 's|"file://([A-Z]):/|"file:///\1:/|g' %/t/definition.jsonrpc.tmp > %/t/definition.jsonrpc
#
# RUN: clangd -experimental-modules-support -lit-test < %t/definition.jsonrpc \
# RUN: | FileCheck -strict-whitespace %t/definition.jsonrpc

#--- A-frag.cppm
export module A:frag;
export void printA() {}

#--- A.cppm
export module A;
export import :frag;

#--- Use.cpp
import A;
void foo() {
print
}

#--- compile_commands.json.tmpl
[
{
"directory": "DIR",
"command": "CLANG_CC -fprebuilt-module-path=DIR -std=c++20 -o DIR/main.cpp.o -c DIR/Use.cpp",
"file": "DIR/Use.cpp"
},
{
"directory": "DIR",
"command": "CLANG_CC -std=c++20 DIR/A.cppm --precompile -o DIR/A.pcm",
"file": "DIR/A.cppm"
},
{
"directory": "DIR",
"command": "CLANG_CC -std=c++20 DIR/A-frag.cppm --precompile -o DIR/A-frag.pcm",
"file": "DIR/A-frag.cppm"
}
]

#--- definition.jsonrpc.tmpl
{
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"processId": 123,
"rootPath": "clangd",
"capabilities": {
"textDocument": {
"completion": {
"completionItem": {
"snippetSupport": true
}
}
}
},
"trace": "off"
}
}
---
{
"jsonrpc": "2.0",
"method": "textDocument/didOpen",
"params": {
"textDocument": {
"uri": "file://DIR/Use.cpp",
"languageId": "cpp",
"version": 1,
"text": "import A;\nvoid foo() {\n print\n}\n"
}
}
}

# CHECK: "message"{{.*}}printA{{.*}}(fix available)

---
{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"file://DIR/Use.cpp"},"context":{"triggerKind":1},"position":{"line":2,"character":6}}}
---
{"jsonrpc":"2.0","id":2,"method":"shutdown"}
---
{"jsonrpc":"2.0","method":"exit"}
10 changes: 5 additions & 5 deletions clang-tools-extra/clangd/test/modules.test
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# A smoke test to check the modules can work basically.
#
# Windows have different escaping modes.
# FIXME: We should add one for windows.
# UNSUPPORTED: system-windows
#
# RUN: rm -fr %t
# RUN: mkdir -p %t
# RUN: split-file %s %t
#
# RUN: sed -e "s|DIR|%/t|g" %t/compile_commands.json.tmpl > %t/compile_commands.json.tmp
# RUN: sed -e "s|CLANG_CC|%clang|g" %t/compile_commands.json.tmp > %t/compile_commands.json
# RUN: sed -e "s|DIR|%/t|g" %t/definition.jsonrpc.tmpl > %t/definition.jsonrpc
# RUN: sed -e "s|DIR|%/t|g" %t/definition.jsonrpc.tmpl > %t/definition.jsonrpc.tmp
#
# On Windows, we need the URI in didOpen to look like "uri":"file:///C:/..."
# (with the extra slash in the front), so we add it here.
# RUN: sed -E -e 's|"file://([A-Z]):/|"file:///\1:/|g' %/t/definition.jsonrpc.tmp > %/t/definition.jsonrpc
#
# RUN: clangd -experimental-modules-support -lit-test < %t/definition.jsonrpc \
# RUN: | FileCheck -strict-whitespace %t/definition.jsonrpc
Expand Down
Loading