[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 26 03:58:58 PDT 2023


================
@@ -0,0 +1,141 @@
+//===----------------- PrerequisiteModules.h -------------------------*-
+//C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Experimental support for C++20 Modules.
+//
+// Currently we simplify the implementations by preventing reusing module files
+// across different versions and different source files. But this is clearly a
+// waste of time and space in the end of the day.
+//
+// FIXME: Supporting reusing module files across different versions and
+// different source files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREREQUISITEMODULES_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREREQUISITEMODULES_H
+
+#include "Compiler.h"
+#include "GlobalCompilationDatabase.h"
+#include "ModuleDependencyScanner.h"
+#include "support/Path.h"
+
+#include "clang/Lex/HeaderSearchOptions.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang {
+namespace clangd {
+
+/// Build and store all the needed module files information to parse a single
+/// source file. e.g.,
+///
+///   ```
+///   // a.cppm
+///   export module a;
+///
+///   // b.cppm
+///   export module b;
+///   import a;
+///
+///   // c.cppm
+///   export module c;
+///   import a;
+///   ```
+///
+/// For the source file `c.cppm`, an instance of the class will build and store
+/// the module files for `a.cppm` and `b.cppm`. But the module file for `c.cppm`
+/// won't be built. Since it is not needed to parse `c.cppm`.
+///
+/// All the built module files won't be shared with other instances of the
+/// class. So that we can avoid worrying thread safety.
+///
+/// A PrerequisiteModules instace should only be initialized by
+/// `PrerequisiteModules::buildPrerequisiteModulesFor(...)`.
+///
+/// Users can detect whether the PrerequisiteModules is still up to date by
+/// calling the `CanReuse()` member function.
+///
+/// The users should call `adjustHeaderSearchOptions(...)` or
+/// `adjustCompileCommands(CompileCommand&)` member function to update the
+/// compilation commands to select the built module files first.
+struct PrerequisiteModules {
----------------
sam-mccall wrote:

this class has a bunch of responsibilities and state transitions. e.g. it has an "invalid" state. modules can be built, not built yet, not buildable, etc.

I think it can be simpler if decomposed into:
 - `struct ModuleFile`, which has a module name, a filename, and deletes the file in its destructor
 - `class PrerequisiteModules` which owns a set of `ModuleFiles` for a particular TU, and knows how to adjust the compile commands etc to use them
 - a function to build `PrerequisiteModules` for a TU. This is currently `static PrerequisiteModules::buildPrerequisiteModulesFor` which is OK, but it can really just create a bunch of `ModuleFile`s and pass it to the PrerequisiteModules constructor. 

(As I mention elsewhere: I think buildPrerquisiteModulesFor should really be a method on a different `ModuleBuilder` object, as it will eventually need to deal with caching and other things)

https://github.com/llvm/llvm-project/pull/66462


More information about the cfe-commits mailing list