[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth closed https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/ChuanqiXu9 approved this pull request. https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
naveen-seth wrote: Done. For the regression test, I've updated it to use `--allow-empty` instead of forcing output using `clang -v` (+formatting & removed duplicate flags). Thank you for the reviews. https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth updated
https://github.com/llvm/llvm-project/pull/145220
>From 2574e28fd8dd33d4042f169576d9927ae0649ff5 Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig
Date: Fri, 13 Jun 2025 09:19:21 +0200
Subject: [PATCH 1/7] [clang][modules-driver] Add scanner to detect C++20
module presence
This PR is part of a series to natively support C++20 module usage
from the Clang driver (without requiring an external build system).
This introduces a new scanner that detects C++20 module usage in
source files without using the preprocessor or lexer.
For now, it is enabled only with the `-fmodules-driver` flag and
serves solely diagnostic purposes. In the future, the scanner will be
enabled for any (modules-driver compatible) compilation with two or
more inputs, and will help the driver determine whether to implicitly
enable the modules driver.
Since the scanner adds very little overhead, we are also exploring
enabling it for compilations with only a single input.
This approach could allow us to detect `import std` usage in a
single-file compilation, which would then activate the modules driver.
For performance measurements on this, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
.../clang/Basic/DiagnosticDriverKinds.td | 13 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Driver/Driver.h | 31 +++
clang/include/clang/Driver/Options.td | 7 +
clang/lib/Driver/Driver.cpp | 215 ++
...ules-driver-cxx20-module-usage-scanner.cpp | 171 ++
clang/test/Frontend/warning-options.cpp | 2 +-
7 files changed, 439 insertions(+), 1 deletion(-)
create mode 100644
clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
+ /// If the compilation is an explicit module build, delegates to
+ /// BuildExplicitModuleBuildActions. Otherwise, uses BuildDefaultActions.
///
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// Buil
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
@@ -577,6 +577,16 @@ def err_drv_reduced_module_output_overrided : Warning< "please consider use '-fmodule-output=' to specify the output file for reduced BMI explicitly">, InGroup>; +def remark_found_cxx20_module_usage : Remark< + "found C++20 module usage in file '%0'">, + InGroup; +def remark_performing_explicit_module_build : Remark< ChuanqiXu9 wrote: I don't like the name "explicit module". It is confusing to me. Please change this to other names. e.g., "clang managed C++ modules build" https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// BuildExplicitModuleBuildActions - Performs a dependency scan and
+ /// constructs the list of actions to perform for dependency order and
+ /// the provided arguments. This is only done for a single a architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildExplicitModuleBuildActions(Compilation &C,
ChuanqiXu9 wrote:
ditto, please change the name `explicit module`.
https://github.com/llvm/llvm-project/pull/145220
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/ChuanqiXu9 edited https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/ChuanqiXu9 requested changes to this pull request. I still hope we can get a new name. It is important for me to understand if some code may affect C++20 module or not by its name. I feel this can be helpful for other developers too. https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth updated
https://github.com/llvm/llvm-project/pull/145220
>From 2574e28fd8dd33d4042f169576d9927ae0649ff5 Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig
Date: Fri, 13 Jun 2025 09:19:21 +0200
Subject: [PATCH 1/5] [clang][modules-driver] Add scanner to detect C++20
module presence
This PR is part of a series to natively support C++20 module usage
from the Clang driver (without requiring an external build system).
This introduces a new scanner that detects C++20 module usage in
source files without using the preprocessor or lexer.
For now, it is enabled only with the `-fmodules-driver` flag and
serves solely diagnostic purposes. In the future, the scanner will be
enabled for any (modules-driver compatible) compilation with two or
more inputs, and will help the driver determine whether to implicitly
enable the modules driver.
Since the scanner adds very little overhead, we are also exploring
enabling it for compilations with only a single input.
This approach could allow us to detect `import std` usage in a
single-file compilation, which would then activate the modules driver.
For performance measurements on this, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
.../clang/Basic/DiagnosticDriverKinds.td | 13 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Driver/Driver.h | 31 +++
clang/include/clang/Driver/Options.td | 7 +
clang/lib/Driver/Driver.cpp | 215 ++
...ules-driver-cxx20-module-usage-scanner.cpp | 171 ++
clang/test/Frontend/warning-options.cpp | 2 +-
7 files changed, 439 insertions(+), 1 deletion(-)
create mode 100644
clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
+ /// If the compilation is an explicit module build, delegates to
+ /// BuildExplicitModuleBuildActions. Otherwise, uses BuildDefaultActions.
///
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// Buil
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/Bigcheese approved this pull request. With the last bit this looks fine to me, but you should wait for Chuanqi and see if the naming should be changed. https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
@@ -0,0 +1,171 @@
+// The driver never checks to implicitly enable the explicit module build
+// support unless at least two input files are provided.
+// To trigger the C++20 module usage check, we always pass a second dummy file
+// as input.
+// TODO: Remove -fmodules everywhere once implicitly enabled explicit module
+// builds are supported.
+
+// RUN: split-file %s %t
+//--- empty.cpp
+// Nothing here
+
+//--- only-global.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/only-global.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK1
+// CHECK1: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+module;
+
+//--- only-import.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/only-import.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK2
+// CHECK2: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+import A;
+
+//--- only-export.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/only-export.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK3
+// CHECK3: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+export module A;
+
+//--- leading-line-comment.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-line-comment.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK4
+// CHECK4: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+// My line comment
+import A;
+
+//--- leading-block-comment1.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-block-comment1.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK5
+// CHECK5: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+/*My block comment */
+import A;
+
+//--- leading-block-comment2.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-block-comment2.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK6
+// CHECK6: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+/*My line comment */ import A;
+
+//--- inline-block-comment1.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-block-comment1.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK7
+// CHECK7: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+export/*a comment*/module/*another comment*/A;
+
+//--- inline-block-comment2.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-block-comment2.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK8
+// CHECK8: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+module/*a comment*/;
+
+//--- leading-directives.cpp
+// RUN: %clang -std=c++23 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-directives.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK9
+// CHECK9: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+#define A
+#undef A
+#if A
+#ifdef A
+#elifdef A
+#elifndef A
+#endif
+#ifndef A
+#elif A
+#else
+#endif
+#endif
+#pragma once;
+#include
+import m;
+
+//--- multiline-directive.cpp
+// RUN: %clang -std=c++23 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/multiline-directive.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK10
+// CHECK10: remark: found C++20 module usage in file '{{.*}}'
[-Rmodules-driver]
+#define MACRO(a, \
+ b) \
+call((a), \
+ (b)
+module;
Bigcheese wrote:
This case has the same problem as above. `import m;` works here too.
https://github.com/llvm/llvm-project/pull/145220
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth updated
https://github.com/llvm/llvm-project/pull/145220
>From 2574e28fd8dd33d4042f169576d9927ae0649ff5 Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig
Date: Fri, 13 Jun 2025 09:19:21 +0200
Subject: [PATCH 1/4] [clang][modules-driver] Add scanner to detect C++20
module presence
This PR is part of a series to natively support C++20 module usage
from the Clang driver (without requiring an external build system).
This introduces a new scanner that detects C++20 module usage in
source files without using the preprocessor or lexer.
For now, it is enabled only with the `-fmodules-driver` flag and
serves solely diagnostic purposes. In the future, the scanner will be
enabled for any (modules-driver compatible) compilation with two or
more inputs, and will help the driver determine whether to implicitly
enable the modules driver.
Since the scanner adds very little overhead, we are also exploring
enabling it for compilations with only a single input.
This approach could allow us to detect `import std` usage in a
single-file compilation, which would then activate the modules driver.
For performance measurements on this, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
.../clang/Basic/DiagnosticDriverKinds.td | 13 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Driver/Driver.h | 31 +++
clang/include/clang/Driver/Options.td | 7 +
clang/lib/Driver/Driver.cpp | 215 ++
...ules-driver-cxx20-module-usage-scanner.cpp | 171 ++
clang/test/Frontend/warning-options.cpp | 2 +-
7 files changed, 439 insertions(+), 1 deletion(-)
create mode 100644
clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
+ /// If the compilation is an explicit module build, delegates to
+ /// BuildExplicitModuleBuildActions. Otherwise, uses BuildDefaultActions.
///
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// Buil
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth updated
https://github.com/llvm/llvm-project/pull/145220
>From 2574e28fd8dd33d4042f169576d9927ae0649ff5 Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig
Date: Fri, 13 Jun 2025 09:19:21 +0200
Subject: [PATCH 1/3] [clang][modules-driver] Add scanner to detect C++20
module presence
This PR is part of a series to natively support C++20 module usage
from the Clang driver (without requiring an external build system).
This introduces a new scanner that detects C++20 module usage in
source files without using the preprocessor or lexer.
For now, it is enabled only with the `-fmodules-driver` flag and
serves solely diagnostic purposes. In the future, the scanner will be
enabled for any (modules-driver compatible) compilation with two or
more inputs, and will help the driver determine whether to implicitly
enable the modules driver.
Since the scanner adds very little overhead, we are also exploring
enabling it for compilations with only a single input.
This approach could allow us to detect `import std` usage in a
single-file compilation, which would then activate the modules driver.
For performance measurements on this, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
.../clang/Basic/DiagnosticDriverKinds.td | 13 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Driver/Driver.h | 31 +++
clang/include/clang/Driver/Options.td | 7 +
clang/lib/Driver/Driver.cpp | 215 ++
...ules-driver-cxx20-module-usage-scanner.cpp | 171 ++
clang/test/Frontend/warning-options.cpp | 2 +-
7 files changed, 439 insertions(+), 1 deletion(-)
create mode 100644
clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
+ /// If the compilation is an explicit module build, delegates to
+ /// BuildExplicitModuleBuildActions. Otherwise, uses BuildDefaultActions.
///
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// Buil
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth updated
https://github.com/llvm/llvm-project/pull/145220
>From 2574e28fd8dd33d4042f169576d9927ae0649ff5 Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig
Date: Fri, 13 Jun 2025 09:19:21 +0200
Subject: [PATCH 1/3] [clang][modules-driver] Add scanner to detect C++20
module presence
This PR is part of a series to natively support C++20 module usage
from the Clang driver (without requiring an external build system).
This introduces a new scanner that detects C++20 module usage in
source files without using the preprocessor or lexer.
For now, it is enabled only with the `-fmodules-driver` flag and
serves solely diagnostic purposes. In the future, the scanner will be
enabled for any (modules-driver compatible) compilation with two or
more inputs, and will help the driver determine whether to implicitly
enable the modules driver.
Since the scanner adds very little overhead, we are also exploring
enabling it for compilations with only a single input.
This approach could allow us to detect `import std` usage in a
single-file compilation, which would then activate the modules driver.
For performance measurements on this, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
.../clang/Basic/DiagnosticDriverKinds.td | 13 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Driver/Driver.h | 31 +++
clang/include/clang/Driver/Options.td | 7 +
clang/lib/Driver/Driver.cpp | 215 ++
...ules-driver-cxx20-module-usage-scanner.cpp | 171 ++
clang/test/Frontend/warning-options.cpp | 2 +-
7 files changed, 439 insertions(+), 1 deletion(-)
create mode 100644
clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
+ /// If the compilation is an explicit module build, delegates to
+ /// BuildExplicitModuleBuildActions. Otherwise, uses BuildDefaultActions.
///
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// Buil
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/Bigcheese edited https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
@@ -4403,6 +4411,174 @@ void Driver::handleArguments(Compilation &C,
DerivedArgList &Args,
}
}
+static void skipWhitespace(const char *&Ptr) {
+ while (isWhitespace(*Ptr))
+++Ptr;
+}
+
+// Returns the length of EOL, either 0 (no end-of-line), 1 (\n) or 2 (\r\n).
+static unsigned isEOL(const char *Ptr) {
+ if (*Ptr == '\0')
+return 0;
+ if (*(Ptr + 1) != '\0' && isVerticalWhitespace(Ptr[0]) &&
+ isVerticalWhitespace(Ptr[1]) && Ptr[0] != Ptr[1])
+return 2;
+ return !!isVerticalWhitespace(Ptr[0]);
+}
+
+static void skipLine(const char *&Ptr) {
+ for (;;) {
+char LastNonWhitespace = ' ';
+while (!isVerticalWhitespace(*Ptr) && *Ptr != '\0') {
+ if (!isHorizontalWhitespace(*Ptr))
+LastNonWhitespace = *Ptr;
+ ++Ptr;
+}
+
+const unsigned Len = isEOL(Ptr);
+if (!Len)
+ return;
+
+Ptr += Len;
+if (LastNonWhitespace != '\\')
+ break;
+ }
+}
+
+// Returns the length of a line splice sequence (including trailing
+// whitespace), or 0 if no line splice is found.
+static unsigned isLineSplice(const char *Start) {
+ if (*Start != '\\')
+return 0;
+
+ const char *Ptr = Start + 1;
+ while (isHorizontalWhitespace(*Ptr))
+++Ptr;
+
+ if (unsigned Len = isEOL(Ptr))
+return Ptr - Start + Len;
+ return 0;
+}
+
+static bool trySkipLineSplice(const char *&Ptr) {
+ if (unsigned Len = isLineSplice(Ptr); Len) {
+Ptr += Len;
+return true;
+ }
+ return false;
+}
+
+static bool trySkipDirective(const char *&Ptr) {
+ if (*Ptr != '#')
+return false;
+
+ ++Ptr;
+ skipLine(Ptr);
+ return true;
+}
+
+static bool trySkipLineComment(const char *&Ptr) {
+ if (Ptr[0] != '/' || Ptr[1] != '/')
+return false;
+
+ Ptr += 2;
+ skipLine(Ptr);
+ return true;
+}
+
+static bool trySkipBlockComment(const char *&Ptr) {
+ if (Ptr[0] != '/' || Ptr[1] != '*')
+return false;
+
+ Ptr += 2;
+ while (*Ptr != '\0') {
+if (Ptr[0] == '*' && Ptr[1] == '/') {
+ Ptr += 2; // '*/'
+ return true;
+}
+++Ptr;
+ }
+ return true;
+}
+
+static bool trySkipComment(const char *&Ptr) {
+ return trySkipLineComment(Ptr) || trySkipBlockComment(Ptr);
+}
+
+// Skipps over comments and (non-module) directives
+static void skipToRelevantCXXModuleText(const char *&Ptr) {
+ while (*Ptr != '\0') {
+skipWhitespace(Ptr);
+if (trySkipComment(Ptr) || trySkipDirective(Ptr) || trySkipLineSplice(Ptr))
+ continue;
+break; // Found relevant text!
+ }
+}
+
+static bool scanBufferForCXXModuleUsage(const llvm::MemoryBuffer &Buffer) {
+ const char *Ptr = Buffer.getBufferStart();
+ skipToRelevantCXXModuleText(Ptr);
+
+ // Check if buffer has enough bytes left to check for the module-related
+ // declaration fragment we want to check without making potentially
Bigcheese wrote:
```suggestion
// declaration fragment we want to check without making the potentially
```
https://github.com/llvm/llvm-project/pull/145220
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning< "please consider use '-fmodule-output=' to specify the output file for reduced BMI explicitly">, InGroup>; +def remark_fmodules_driver_enabled : Remark< + "support for explicit module builds enabled (experimental)">, Bigcheese wrote: I don't think this specific remark is needed, it's just saying the flag is passed, which is simple enough to not need a remark for. https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
@@ -0,0 +1,171 @@
+// The driver never checks to implicitly enable the explicit module build
+// support unless at least two input files are provided.
+// To trigger the C++20 module usage check, we always pass a second dummy file
+// as input.
+// TODO: Remove -fmodules everywhere once implicitly enabled explicit module
+// builds are supported.
+
+// RUN: split-file %s %t
+//--- empty.cpp
+// Nothing here
+
+//--- only-global.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/only-global.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK1
+// CHECK1: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+module;
+
+//--- only-import.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/only-import.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK2
+// CHECK2: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+import A;
+
+//--- only-export.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/only-export.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK3
+// CHECK3: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+export module A;
+
+//--- leading-line-comment.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-line-comment.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK4
+// CHECK4: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+// My line comment
+import A;
+
+//--- leading-block-comment1.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-block-comment1.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK5
+// CHECK5: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+/*My block comment */
+import A;
+
+//--- leading-block-comment2.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-block-comment2.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK6
+// CHECK6: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+/*My line comment */ import A;
+
+//--- inline-block-comment1.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-block-comment1.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK7
+// CHECK7: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+export/*a comment*/module/*another comment*/A;
+
+//--- inline-block-comment2.cpp
+// RUN: %clang -std=c++20 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-block-comment2.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK8
+// CHECK8: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+module/*a comment*/;
+
+//--- leading-directives.cpp
+// RUN: %clang -std=c++23 -ccc-print-phases -fmodules-driver -Rmodules-driver \
+// RUN: %t/leading-directives.cpp %t/empty.cpp 2>&1 | FileCheck %s
--check-prefix=CHECK9
+// CHECK9: remark: found C++20 module usage in file '{{.*}}' [-Rmodules-driver]
+#define A
+#undef A
+#if A
+#ifdef A
+#elifdef A
+#elifndef A
+#endif
+#ifndef A
+#elif A
+#else
+#endif
+#endif
+#pragma once;
+#include
+export module m;
Bigcheese wrote:
This is invalid per [P1857](https://wg21.link/P1857). It has to start with
`module;`, which messed up the test. I think you can just do `import m;` here
instead.
https://github.com/llvm/llvm-project/pull/145220
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
@@ -4414,6 +4590,34 @@ void Driver::BuildActions(Compilation &C, DerivedArgList
&Args,
handleArguments(C, Args, Inputs, Actions);
+ if (Args.hasFlag(options::OPT_fmodules_driver,
+ options::OPT_fno_modules_driver, false)) {
+Diags.Report(diag::remark_fmodules_driver_enabled);
+// TODO: Move the logic for implicitly enabling explicit-module-builds out
+// of -fmodules-driver once it is no longer experimental.
+// Currently, this serves diagnostic purposes only.
+bool UsesCXXModules = hasCXXModuleInputType(Inputs);
+if (!UsesCXXModules) {
+ const auto ErrOrScanResult = ScanInputsForCXXModuleUsage(Inputs);
+ if (!ErrOrScanResult) {
+Diags.Report(diag::err_cannot_open_file)
+<< ErrOrScanResult.getError().message();
+return;
+ }
+ UsesCXXModules = *ErrOrScanResult;
+}
+if (UsesCXXModules)
+ BuildExplicitModuleBuildActions(C, Args, Inputs, Actions);
+return;
+ }
+
+ Driver::BuildDefaultActions(C, Args, Inputs, Actions);
Bigcheese wrote:
No need to `Driver::` qualify this.
https://github.com/llvm/llvm-project/pull/145220
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/ChuanqiXu9 commented: I prefer to change the term "explicit module" in the code to something like `CXX20 module` or `named module` or whatever. Since when I read the term `explicit module` I assumed it is a style to build clang header modules. https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
Bigcheese wrote: > > This PR is part of a series aimed at implementing native support for > > explicit module builds from the Clang driver. > > This is confusing. Since explicit modules is an unrelated term with C++20 > modules. All C++20 named modules builds are done explicitly at the moment. The terminology isn't perfect, but explicitly built means there's a call to `clang -cc1 -emit-module` and implicitly built means the compiler does it internally. This will also eventually support C++20 named modules with Clang modules acting as header units, as well as just stand alone Clang modules. https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
ChuanqiXu9 wrote: > This PR is part of a series aimed at implementing native support for explicit > module builds from the Clang driver. This is confusing. Since explicit modules is an unrelated term with C++20 modules. https://github.com/llvm/llvm-project/pull/145220 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth updated
https://github.com/llvm/llvm-project/pull/145220
>From cc92d075db7e9b0cd4c8187e9dc8e20bf4151fdc Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig
Date: Fri, 13 Jun 2025 09:19:21 +0200
Subject: [PATCH 1/2] [clang][modules-driver] Add scanner to detect C++20
module presence
This PR is part of a series aimed at implementing native support for
explicit module builds from the Clang driver.
This introduces a new scanner that detects C++20 module usage in
source files without using the preprocessor or lexer.
For now, it is enabled only with the -fmodules-driver flag and serves
solely diagnostic purposes. In the future, the scanner will help the
driver determine whether to implicitly perform an explicit module
build and will be enabled for any (modules-driver compatible)
compilation with 2 or more inputs.
Since the scanner adds very little overhead, we are also exploring
enabling it for compilations with only a single input.
This approach could allow us to detect `import std` usage in a
single-file compilation, which would then activate the modules driver.
For performance measurements, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
.../clang/Basic/DiagnosticDriverKinds.td | 13 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Driver/Driver.h | 31 +++
clang/include/clang/Driver/Options.td | 7 +
clang/lib/Driver/Driver.cpp | 215 ++
...ules-driver-cxx20-module-usage-scanner.cpp | 171 ++
clang/test/Frontend/warning-options.cpp | 2 +-
7 files changed, 439 insertions(+), 1 deletion(-)
create mode 100644
clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
+ /// If the compilation is an explicit module build, delegates to
+ /// BuildExplicitModuleBuildActions. Otherwise, uses BuildDefaultActions.
///
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// BuildExplicitModuleBuildAction
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth updated
https://github.com/llvm/llvm-project/pull/145220
>From cc92d075db7e9b0cd4c8187e9dc8e20bf4151fdc Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig
Date: Fri, 13 Jun 2025 09:19:21 +0200
Subject: [PATCH] [clang][modules-driver] Add scanner to detect C++20 module
presence
This PR is part of a series aimed at implementing native support for
explicit module builds from the Clang driver.
This introduces a new scanner that detects C++20 module usage in
source files without using the preprocessor or lexer.
For now, it is enabled only with the -fmodules-driver flag and serves
solely diagnostic purposes. In the future, the scanner will help the
driver determine whether to implicitly perform an explicit module
build and will be enabled for any (modules-driver compatible)
compilation with 2 or more inputs.
Since the scanner adds very little overhead, we are also exploring
enabling it for compilations with only a single input.
This approach could allow us to detect `import std` usage in a
single-file compilation, which would then activate the modules driver.
For performance measurements, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
.../clang/Basic/DiagnosticDriverKinds.td | 13 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Driver/Driver.h | 31 +++
clang/include/clang/Driver/Options.td | 7 +
clang/lib/Driver/Driver.cpp | 215 ++
...ules-driver-cxx20-module-usage-scanner.cpp | 171 ++
clang/test/Frontend/warning-options.cpp | 2 +-
7 files changed, 439 insertions(+), 1 deletion(-)
create mode 100644
clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
+ /// If the compilation is an explicit module build, delegates to
+ /// BuildExplicitModuleBuildActions. Otherwise, uses BuildDefaultActions.
///
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// BuildExplicitModuleBuildActions -
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
https://github.com/naveen-seth created
https://github.com/llvm/llvm-project/pull/145220
This PR is part of a series aimed at implementing native support for explicit
module builds from the Clang driver.
This introduces a new scanner that detects C++20 module usage in source files
without using the preprocessor or lexer.
For now, it is enabled only with the -fmodules-driver flag and serves solely
diagnostic purposes. In the future, the scanner will help the driver determine
whether to implicitly perform an explicit module build and will be enabled for
any (modules-driver compatible) compilation with 2 or more inputs.
Since the scanner adds very little overhead, we are also exploring enabling it
for compilations with only a single input. This approach could allow us to
detect `import std` usage in a single-file compilation, which would then
activate the modules driver. For performance measurements, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
>From 31d39ccf3caf83148f865dabf79c236881ad6d7b Mon Sep 17 00:00:00 2001
From: Naveen Seth Hanig
Date: Fri, 13 Jun 2025 09:19:21 +0200
Subject: [PATCH] [clang][modules-driver] Add scanner to detect C++20 module
presence
This PR is part of a series aimed at implementing native support for
explicit module builds from the Clang driver.
This introduces a new scanner that detects C++20 module usage in
source files without using the preprocessor or lexer.
For now, it is enabled only with the -fmodules-driver flag and serves
solely diagnostic purposes. In the future, the scanner will help the
driver determine whether to implicitly perform an explicit module
build and will be enabled for any (modules-driver compatible)
compilation with 2 or more inputs.
Since the scanner adds very little overhead, we are also exploring
enabling it for compilations with only a single input.
This approach could allow us to detect `import std` usage in a
single-file compilation, which would then activate the modules driver.
For performance measurements, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
.../clang/Basic/DiagnosticDriverKinds.td | 13 ++
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
clang/include/clang/Driver/Driver.h | 31 +++
clang/include/clang/Driver/Options.td | 7 +
clang/lib/Driver/Driver.cpp | 215 ++
...ules-driver-cxx20-module-usage-scanner.cpp | 171 ++
6 files changed, 438 insertions(+)
create mode 100644
clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a si
[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
llvmbot wrote:
@llvm/pr-subscribers-clang-driver
@llvm/pr-subscribers-clang
Author: Naveen Seth Hanig (naveen-seth)
Changes
This PR is part of a series aimed at implementing native support for explicit
module builds from the Clang driver.
This introduces a new scanner that detects C++20 module usage in source files
without using the preprocessor or lexer.
For now, it is enabled only with the -fmodules-driver flag and serves solely
diagnostic purposes. In the future, the scanner will help the driver determine
whether to implicitly perform an explicit module build and will be enabled for
any (modules-driver compatible) compilation with 2 or more inputs.
Since the scanner adds very little overhead, we are also exploring enabling it
for compilations with only a single input. This approach could allow us to
detect `import std` usage in a single-file compilation, which would then
activate the modules driver. For performance measurements, see
https://github.com/naveen-seth/llvm-dev-cxx-modules-check-benchmark.
RFC:
https://discourse.llvm.org/t/rfc-modules-support-simple-c-20-modules-use-from-the-clang-driver-without-a-build-system
---
Patch is 20.73 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/145220.diff
6 Files Affected:
- (modified) clang/include/clang/Basic/DiagnosticDriverKinds.td (+13)
- (modified) clang/include/clang/Basic/DiagnosticGroups.td (+1)
- (modified) clang/include/clang/Driver/Driver.h (+31)
- (modified) clang/include/clang/Driver/Options.td (+7)
- (modified) clang/lib/Driver/Driver.cpp (+215)
- (added) clang/test/Driver/modules-driver-cxx20-module-usage-scanner.cpp
(+171)
``diff
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 29f6480ba935c..9ed50b6807d2a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -577,6 +577,19 @@ def err_drv_reduced_module_output_overrided : Warning<
"please consider use '-fmodule-output=' to specify the output file for
reduced BMI explicitly">,
InGroup>;
+def remark_fmodules_driver_enabled : Remark<
+ "support for explicit module builds enabled (experimental)">,
+ InGroup;
+def remark_found_cxx20_module_usage : Remark<
+ "found C++20 module usage in file '%0'">,
+ InGroup;
+def remark_performing_explicit_module_build : Remark<
+ "performing explicit module build">,
+ InGroup;
+def warn_modules_driver_unsupported_standard : Warning<
+ "'-fmodules-driver' is not supported before C++20">,
+ InGroup;
+
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
InGroup>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td
b/clang/include/clang/Basic/DiagnosticGroups.td
index beda73e675fc6..1baede2d0c324 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -625,6 +625,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
def ModuleFileExtension : DiagGroup<"module-file-extension">;
def ModuleIncludeDirectiveTranslation :
DiagGroup<"module-include-translation">;
def ModuleMap : DiagGroup<"module-map">;
+def ModulesDriver : DiagGroup<"modules-driver">;
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
def NewlineEOF : DiagGroup<"newline-eof">;
def Nullability : DiagGroup<"nullability">;
diff --git a/clang/include/clang/Driver/Driver.h
b/clang/include/clang/Driver/Driver.h
index 7ca848f11b561..9f9518942270a 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -505,6 +505,8 @@ class Driver {
/// BuildActions - Construct the list of actions to perform for the
/// given arguments, which are only done for a single architecture.
+ /// If the compilation is an explicit module build, delegates to
+ /// BuildExplicitModuleBuildActions. Otherwise, uses BuildDefaultActions.
///
/// \param C - The compilation that is being built.
/// \param Args - The input arguments.
@@ -790,6 +792,35 @@ class Driver {
/// compilation based on which -f(no-)?lto(=.*)? option occurs last.
void setLTOMode(const llvm::opt::ArgList &Args);
+ /// BuildDefaultActions - Constructs the list of actions to perform
+ /// for the provided arguments, which are only done for a single
architecture.
+ ///
+ /// \param C - The compilation that is being built.
+ /// \param Args - The input arguments.
+ /// \param Actions - The list to store the resulting actions onto.
+ void BuildDefaultActions(Compilation &C, llvm::opt::DerivedArgList &Args,
+ const InputList &Inputs, ActionList &Actions) const;
+
+ /// BuildExplicitModuleBuildActions - Performs a dependency scan and
+ /// constructs the list of actions to perform for dependency order and
+ /// the provided arguments. This is only done for a single a architecture.
+ //
