Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clangd] [C++20] [Modules] Introduce initial support for C++20 Modules #66462

Merged
merged 8 commits into from
Jul 18, 2024
2 changes: 0 additions & 2 deletions clang-tools-extra/clangd/ClangdLSPServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@
namespace clang {
namespace clangd {

extern llvm::cl::opt<bool> ExperimentalModulesSupport;

namespace {
// Tracks end-to-end latency of high level lsp calls. Measurements are in
// seconds.
Expand Down
43 changes: 19 additions & 24 deletions clang-tools-extra/clangd/ModulesBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@
//===----------------------------------------------------------------------===//

#include "ModulesBuilder.h"

#include "Compiler.h"
#include "support/Logger.h"

#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"

#include "clang/Serialization/ASTReader.h"

namespace clang {
Expand Down Expand Up @@ -142,8 +139,6 @@ class StandalonePrerequisiteModules : public PrerequisiteModules {
ModuleFile(llvm::StringRef ModuleName, PathRef ModuleFilePath)
: ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}

ModuleFile() = delete;

ModuleFile(const ModuleFile &) = delete;
ModuleFile operator=(const ModuleFile &) = delete;

Expand Down Expand Up @@ -187,23 +182,21 @@ llvm::Error buildModuleFile(llvm::StringRef ModuleName,
// third party modules, we should return true instead of false here.
// Currently we simply bail out.
if (ModuleUnitFileName.empty())
return llvm::createStringError(llvm::formatv(
"Failed to build '{0}': Failed to get the primary source", ModuleName));
return llvm::createStringError(
llvm::formatv("Failed to get the primary source"));
Copy link
Member

Choose a reason for hiding this comment

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

no need for formatv

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


// Try cheap operation earlier to boil-out cheaply if there are problems.
auto Cmd = CDB.getCompileCommand(ModuleUnitFileName);
if (!Cmd)
return llvm::createStringError(
llvm::formatv("Failed to build '{0}': No compile command for {1}",
ModuleName, ModuleUnitFileName));
llvm::formatv("No compile command for {0}", ModuleUnitFileName));

for (auto &RequiredModuleName : MDB.getRequiredModules(ModuleUnitFileName)) {
// Return early if there are errors building the module file.
if (llvm::Error Err = buildModuleFile(RequiredModuleName, CDB, TFS, MDB,
ModuleFilesPrefix, BuiltModuleFiles))
return llvm::createStringError(
llvm::formatv("Failed to build dependency {0}: {1}",
RequiredModuleName, toString(std::move(Err))));
llvm::formatv("Failed to build dependency {0}", RequiredModuleName));
Copy link
Member

Choose a reason for hiding this comment

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

can you also add the underlying error? e.g.: "Failed to build dependency {0}: {1}", RequiredModuleName, llvm::toString(std::move(Err))

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

}

Cmd->Output = getModuleFilePath(ModuleName, ModuleFilesPrefix);
Expand All @@ -215,16 +208,17 @@ llvm::Error buildModuleFile(llvm::StringRef ModuleName,
IgnoreDiagnostics IgnoreDiags;
auto CI = buildCompilerInvocation(Inputs, IgnoreDiags);
if (!CI)
return llvm::createStringError(llvm::formatv(
"Failed to build '{0}': Failed to build compiler invocation for {1}",
ModuleName, ModuleUnitFileName));
return llvm::createStringError(
llvm::formatv("Failed to build compiler invocation"));
Copy link
Member

Choose a reason for hiding this comment

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

no need for formatv

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


auto FS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
auto Buf = FS->getBufferForFile(Inputs.CompileCommand.Filename);
if (!Buf)
return llvm::createStringError(
llvm::formatv("Failed to build '{0}': Failed to create buffer for {1}",
ModuleName, Inputs.CompileCommand.Filename));
return llvm::createStringError(llvm::formatv("Failed to create buffer"));
Copy link
Member

Choose a reason for hiding this comment

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

no need for formatv

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


// In clang's driver, we will suppress the check for ODR violation in GMF.
// See the implementation of RenderModulesOptions in Clang.cpp.
CI->getLangOpts().SkipODRCheckInGMF = true;

// Hash the contents of input files and store the hash value to the BMI files.
// So that we can check if the files are still valid when we want to reuse the
Expand All @@ -238,17 +232,14 @@ llvm::Error buildModuleFile(llvm::StringRef ModuleName,
prepareCompilerInstance(std::move(CI), /*Preamble=*/nullptr,
std::move(*Buf), std::move(FS), IgnoreDiags);
if (!Clang)
return llvm::createStringError(llvm::formatv(
"Failed to build '{0}': Failed to prepare compiler instance for {0}",
ModuleName, ModuleUnitFileName));
return llvm::createStringError(
llvm::formatv("Failed to prepare compiler instance"));
Copy link
Member

Choose a reason for hiding this comment

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

no need for formatv

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


GenerateModuleInterfaceAction Action;
GenerateReducedModuleInterfaceAction Action;
Clang->ExecuteAction(Action);

if (Clang->getDiagnostics().hasErrorOccurred())
return llvm::createStringError(
llvm::formatv("Failed to build '{0}': Compilation for {1} failed",
ModuleName, ModuleUnitFileName));
return llvm::createStringError(llvm::formatv("Compilation failed"));
Copy link
Member

Choose a reason for hiding this comment

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

no need for formatv

Copy link
Member Author

Choose a reason for hiding this comment

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

Done


BuiltModuleFiles.addModuleFile(ModuleName, Inputs.CompileCommand.Output);
return llvm::Error::success();
Expand Down Expand Up @@ -318,6 +309,10 @@ bool StandalonePrerequisiteModules::canReuse(
Clang.getHeaderSearchOpts().ForceCheckCXX20ModulesInputFiles = true;
Clang.getHeaderSearchOpts().ValidateASTInputFilesContent = true;

// Following the practice of clang's driver to suppres the checking for ODR
kadircet marked this conversation as resolved.
Show resolved Hide resolved
// violation in GMF.
Clang.getLangOpts().SkipODRCheckInGMF = true;

Clang.createASTReader();
for (auto &RequiredModule : RequiredModules) {
llvm::StringRef BMIPath = RequiredModule.ModuleFilePath;
Expand Down
4 changes: 0 additions & 4 deletions clang-tools-extra/clangd/ModulesBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,10 @@

#include "GlobalCompilationDatabase.h"
#include "ProjectModules.h"

#include "support/Path.h"
#include "support/ThreadsafeFS.h"

#include "clang/Frontend/CompilerInvocation.h"

#include "llvm/ADT/SmallString.h"

#include <memory>

namespace clang {
Expand Down
9 changes: 7 additions & 2 deletions clang-tools-extra/clangd/ScanningProjectModules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
//===----------------------------------------------------------------------===//

#include "ProjectModules.h"

#include "support/Logger.h"

#include "clang/Driver/Driver.h"
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
#include "clang/Tooling/DependencyScanning/DependencyScanningTool.h"

Expand Down Expand Up @@ -99,6 +98,12 @@ ModuleDependencyScanner::scan(PathRef FilePath) {
// DirectoryBasedGlobalCompilationDatabase::getCompileCommand.
tooling::CompileCommand Cmd = std::move(Candidates.front());
kadircet marked this conversation as resolved.
Show resolved Hide resolved

Cmd.CommandLine.push_back("-I");
llvm::SmallString<256> ResourceDir(clang::driver::Driver::GetResourcesPath(
llvm::sys::fs::getMainExecutable(nullptr, nullptr)));
llvm::sys::path::append(ResourceDir, "include");
Cmd.CommandLine.push_back((std::string)ResourceDir);

using namespace clang::tooling::dependencies;

llvm::SmallString<128> FilePathDir(FilePath);
Expand Down
12 changes: 10 additions & 2 deletions clang-tools-extra/clangd/tool/Check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,13 @@ class Checker {
ClangdLSPServer::Options Opts;
// from buildCommand
tooling::CompileCommand Cmd;
std::unique_ptr<GlobalCompilationDatabase> BaseCDB;
std::unique_ptr<GlobalCompilationDatabase> CDB;
// from buildInvocation
ParseInputs Inputs;
std::unique_ptr<CompilerInvocation> Invocation;
format::FormatStyle Style;
std::optional<ModulesBuilder> ModulesManager;
// from buildAST
std::shared_ptr<const PreambleData> Preamble;
std::optional<ParsedAST> AST;
Expand All @@ -168,14 +171,14 @@ class Checker {
DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS);
CDBOpts.CompileCommandsDir =
Config::current().CompileFlags.CDBSearch.FixedCDBPath;
std::unique_ptr<GlobalCompilationDatabase> BaseCDB =
BaseCDB =
std::make_unique<DirectoryBasedGlobalCompilationDatabase>(CDBOpts);
auto Mangler = CommandMangler::detect();
Mangler.SystemIncludeExtractor =
getSystemIncludeExtractor(llvm::ArrayRef(Opts.QueryDriverGlobs));
if (Opts.ResourceDir)
Mangler.ResourceDir = *Opts.ResourceDir;
auto CDB = std::make_unique<OverlayCDB>(
CDB = std::make_unique<OverlayCDB>(
BaseCDB.get(), std::vector<std::string>{}, std::move(Mangler));

if (auto TrueCmd = CDB->getCompileCommand(File)) {
Expand Down Expand Up @@ -213,6 +216,11 @@ class Checker {
return false;
}
}
if (Opts.EnableExperimentalModulesSupport) {
if (!ModulesManager)
ModulesManager.emplace(*CDB);
Inputs.ModulesManager = &*ModulesManager;
}
log("Parsing command...");
Invocation =
buildCompilerInvocation(Inputs, CaptureInvocationDiags, &CC1Args);
Expand Down
Loading
Loading