From 2599a9aeb543f01cb20e3fdc2713aa8c8cb20fbf Mon Sep 17 00:00:00 2001
From: Ashwin Banwari
Date: Tue, 1 Jul 2025 18:52:10 -0700
Subject: [PATCH] [clang] [modules] Implement P3618R0: Allow attaching main to
the global module (#146461)
Remove the prior warning for attaching extern "C++" to main.
---
clang/docs/ReleaseNotes.rst | 2 ++
clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 +++---
clang/lib/Sema/SemaDecl.cpp | 9 +++------
.../basic/basic.start/basic.start.main/p3.cpp | 5 +++--
clang/test/SemaCXX/modules.cppm | 2 ++
clang/www/cxx_status.html | 2 +-
libcxx/utils/libcxx/test/features.py | 16 +++++++++++++---
7 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7af5f116ee98..3d893e0aa8e2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -135,6 +135,8 @@ C++2c Feature Support
- Implemented `P2719R4 Type-aware allocation and deallocation functions `_.
+- Implemented `P3618R0 Allow attaching main to the global module `_.
+
C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5062505cf3c0..6e48f3bc88ba 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1084,9 +1084,9 @@ def warn_main_redefined : Warning<"variable named 'main' with external linkage "
"has undefined behavior">, InGroup;
def ext_main_used : Extension<
"referring to 'main' within an expression is a Clang extension">, InGroup;
-def ext_main_invalid_linkage_specification : ExtWarn<
- "'main' should not be "
- "'extern \"%select{C|C++}0\"'">, InGroup;
+def ext_main_invalid_linkage_specification : ExtWarn<"'main' should not be "
+ "'extern \"C\"'">,
+ InGroup;
/// parser diagnostics
def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a34e2c9cbb00..61b82b8377e2 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12400,12 +12400,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
void Sema::CheckMain(FunctionDecl *FD, const DeclSpec &DS) {
// [basic.start.main]p3
- // The main function shall not be declared with a linkage-specification.
- if (FD->isExternCContext() ||
- (FD->isExternCXXContext() &&
- FD->getDeclContext()->getRedeclContext()->isTranslationUnit()))
- Diag(FD->getLocation(), diag::ext_main_invalid_linkage_specification)
- << FD->getLanguageLinkage();
+ // The main function shall not be declared with C linkage-specification.
+ if (FD->isExternCContext())
+ Diag(FD->getLocation(), diag::ext_main_invalid_linkage_specification);
// C++11 [basic.start.main]p3:
// A program that [...] declares main to be inline, static or
diff --git a/clang/test/CXX/basic/basic.start/basic.start.main/p3.cpp b/clang/test/CXX/basic/basic.start/basic.start.main/p3.cpp
index 497a9328c115..a8cd523b0837 100644
--- a/clang/test/CXX/basic/basic.start/basic.start.main/p3.cpp
+++ b/clang/test/CXX/basic/basic.start/basic.start.main/p3.cpp
@@ -102,11 +102,12 @@ namespace ns {
}
#elif TEST13
+// expected-no-diagnostics
extern "C++" {
- int main(); // expected-warning {{'main' should not be 'extern "C++"'}}
+ int main();
}
-extern "C++" int main(); // expected-warning {{'main' should not be 'extern "C++"'}}
+extern "C++" int main();
namespace ns1 {
extern "C++" int main(); // ok
diff --git a/clang/test/SemaCXX/modules.cppm b/clang/test/SemaCXX/modules.cppm
index 5d0d6da44a2e..ddbbc7cd8636 100644
--- a/clang/test/SemaCXX/modules.cppm
+++ b/clang/test/SemaCXX/modules.cppm
@@ -68,6 +68,8 @@ int n;
//--- test3.cpp
export module bar;
+extern "C++" int main() {}
+
static int m;
int n;
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index a70e65e35d5e..e5f51bfb2e36 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -317,7 +317,7 @@ C++23, informally referred to as C++26.
| Attaching main to the global module |
P3618R0 (DR) |
- No |
+ Clang 21 |
| Expansion Statements |
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index 74746e37d3bc..c478d99fbed0 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -336,12 +336,22 @@ DEFAULT_FEATURES = [
or platform.system().lower().startswith("aix")
# Avoid building on platforms that don't support modules properly.
or not hasCompileFlag(cfg, "-Wno-reserved-module-identifier")
- or not sourceBuilds(
- cfg,
- """
+ # older versions don't support extern "C++", newer versions don't support main in named module.
+ or not (
+ sourceBuilds(
+ cfg,
+ """
+ export module test;
+ extern "C++" int main(int, char**) { return 0; }
+ """,
+ )
+ or sourceBuilds(
+ cfg,
+ """
export module test;
int main(int, char**) { return 0; }
""",
+ )
),
),
# The time zone validation tests compare the output of zdump against the