Skip to content

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Oct 8, 2025

In the libc++ test suite, we consistently declare main() functions with full parameters and explicitly return from the function. This helps code that compiles the tests with -ffreestanding, where main() is not a special function (with an implicit return and special mangling).

This patch fixes a few stray declarations, including in libunwind and libc++abi.

In the libc++ test suite, we consistently declare main() functions with
full parameters and explicitly return from the function. This helps
code that compiles the tests with -ffreestanding, where main() is not
a special function (with an implicit return and special mangling).
@ldionne ldionne requested review from a team as code owners October 8, 2025 20:48
@llvmbot llvmbot added libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. libc++abi libc++abi C++ Runtime Library. Not libc++. libunwind labels Oct 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-libcxxabi

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

In the libc++ test suite, we consistently declare main() functions with full parameters and explicitly return from the function. This helps code that compiles the tests with -ffreestanding, where main() is not a special function (with an implicit return and special mangling).

This patch fixes a few stray declarations, including in libunwind and libc++abi.


Full diff: https://github.com/llvm/llvm-project/pull/162548.diff

14 Files Affected:

  • (modified) libcxx/test/std/localization/codecvt_unicode.pass.cpp (+2-1)
  • (modified) libcxx/test/std/ranges/range.access/include.iterator.pass.cpp (+2-1)
  • (modified) libcxx/utils/libcxx/test/dsl.py (+1-1)
  • (modified) libcxx/utils/libcxx/test/features.py (+4-4)
  • (modified) libcxxabi/test/forced_unwind4.pass.cpp (+2-2)
  • (modified) libcxxabi/test/native/AArch64/ra_sign_state.pass.cpp (+1-1)
  • (modified) libunwind/test/aarch64_vg_unwind.pass.cpp (+4-1)
  • (modified) libunwind/test/aix_signal_unwind.pass.sh.S (+2-1)
  • (modified) libunwind/test/bad_unwind_info.pass.cpp (+4-1)
  • (modified) libunwind/test/eh_frame_fde_pc_range.pass.cpp (+2-2)
  • (modified) libunwind/test/floatregister.pass.cpp (+1-1)
  • (modified) libunwind/test/forceunwind.pass.cpp (+1-1)
  • (modified) libunwind/test/unw_resume.pass.cpp (+1-1)
  • (modified) libunwind/test/unwind_scalable_vectors.pass.cpp (+5-2)
diff --git a/libcxx/test/std/localization/codecvt_unicode.pass.cpp b/libcxx/test/std/localization/codecvt_unicode.pass.cpp
index fc5625d8ce4e9..523c31625eef2 100644
--- a/libcxx/test/std/localization/codecvt_unicode.pass.cpp
+++ b/libcxx/test/std/localization/codecvt_unicode.pass.cpp
@@ -2222,10 +2222,11 @@ void test_utf16_ucs2_codecvts() {
 #endif
 }
 
-int main() {
+int main(int, char**) {
   test_utf8_utf32_codecvts();
   test_utf8_utf16_codecvts();
   test_utf8_ucs2_codecvts();
   test_utf16_utf32_codecvts();
   test_utf16_ucs2_codecvts();
+  return 0;
 }
diff --git a/libcxx/test/std/ranges/range.access/include.iterator.pass.cpp b/libcxx/test/std/ranges/range.access/include.iterator.pass.cpp
index bb2cda0e4d906..947eb17a2b422 100644
--- a/libcxx/test/std/ranges/range.access/include.iterator.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/include.iterator.pass.cpp
@@ -62,7 +62,8 @@ constexpr bool test() {
   return true;
 }
 
-int main() {
+int main(int, char**) {
   test();
   static_assert(test());
+  return 0;
 }
diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py
index 9a97e61efbe7d..2d3a72c4996ca 100644
--- a/libcxx/utils/libcxx/test/dsl.py
+++ b/libcxx/utils/libcxx/test/dsl.py
@@ -296,7 +296,7 @@ def hasAnyLocale(config, locales):
         + name_string_literals
         + """, nullptr,
       };
-      int main() {
+      int main(int, char**) {
         for (size_t i = 0; test_locale_names[i]; i++) {
           if (::setlocale(LC_ALL, test_locale_names[i]) != NULL) {
             return 0;
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index a964f3bdeeb46..892a592cd0596 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -30,7 +30,7 @@ def _getAndroidDeviceApi(cfg):
             r"""
                 #include <android/api-level.h>
                 #include <stdio.h>
-                int main() {
+                int main(int, char**) {
                     printf("%d\n", android_get_device_api_level());
                     return 0;
                 }
@@ -66,7 +66,7 @@ def _mingwSupportsModules(cfg):
         #else
         // __MINGW64_VERSION_MAJOR > 12 should be ok.
         #endif
-        int main() { return 0; }
+        int main(int, char**) { return 0; }
         """,
     )
 
@@ -474,7 +474,7 @@ def _getLocaleFlagsAction(cfg, locale, alts, members):
         #include <wchar.h>
 
         // Print each requested locale conversion member on separate lines.
-        int main() {
+        int main(int, char**) {
           const char* locales[] = { %s };
           for (int loc_i = 0; loc_i < %d; ++loc_i) {
             if (!setlocale(LC_ALL, locales[loc_i])) {
@@ -629,7 +629,7 @@ def _getLocaleFlagsAction(cfg, locale, alts, members):
             """
             #include <stdio.h>
             #include <windows.h>
-            int main() {
+            int main(int, char**) {
               CHAR tempDirPath[MAX_PATH];
               DWORD tempPathRet = GetTempPathA(MAX_PATH, tempDirPath);
               if (tempPathRet == 0 || tempPathRet > MAX_PATH) {
diff --git a/libcxxabi/test/forced_unwind4.pass.cpp b/libcxxabi/test/forced_unwind4.pass.cpp
index 15efca8d93162..241bc29824561 100644
--- a/libcxxabi/test/forced_unwind4.pass.cpp
+++ b/libcxxabi/test/forced_unwind4.pass.cpp
@@ -17,7 +17,7 @@
 
 // Android/Bionic does not support pthread_cancel.
 #ifdef __BIONIC__
-int main() {
+int main(int, char**) {
   return 0;
 }
 #else
@@ -45,7 +45,7 @@ static void* test(void* arg) {
   return (void*)1;
 }
 
-int main() {
+int main(int, char**) {
   pthread_t child_thread;
   std::unique_lock<std::mutex> lk(cv_m);
   pthread_create(&child_thread, 0, test, (void*)0);
diff --git a/libcxxabi/test/native/AArch64/ra_sign_state.pass.cpp b/libcxxabi/test/native/AArch64/ra_sign_state.pass.cpp
index 35c05fc40efd4..dec7acab7c21e 100644
--- a/libcxxabi/test/native/AArch64/ra_sign_state.pass.cpp
+++ b/libcxxabi/test/native/AArch64/ra_sign_state.pass.cpp
@@ -53,7 +53,7 @@ void bazz() {
   }
 }
 
-int main() {
+int main(int, char**) {
   try {
     bazz();
   } catch (int i) {
diff --git a/libunwind/test/aarch64_vg_unwind.pass.cpp b/libunwind/test/aarch64_vg_unwind.pass.cpp
index b6bb9693c1e0f..1c139a7ae9e41 100644
--- a/libunwind/test/aarch64_vg_unwind.pass.cpp
+++ b/libunwind/test/aarch64_vg_unwind.pass.cpp
@@ -62,4 +62,7 @@ __attribute__((noinline)) void foo() {
   // smstop sm
 }
 
-int main() { foo(); }
+int main(int, char **) {
+  foo();
+  return 0;
+}
diff --git a/libunwind/test/aix_signal_unwind.pass.sh.S b/libunwind/test/aix_signal_unwind.pass.sh.S
index 2c0cf140fe267..bd0b8ac17feea 100644
--- a/libunwind/test/aix_signal_unwind.pass.sh.S
+++ b/libunwind/test/aix_signal_unwind.pass.sh.S
@@ -126,10 +126,11 @@ extern "C" __attribute__((noinline)) void foo() {
   bar();
 }
 
-int main() {
+int main(int, char**) {
   // Set signal handler for SIGSEGV.
   signal(SIGSEGV, handler);
   foo();
+  return 0;
 }
 
 #else // Assembly code for abc().
diff --git a/libunwind/test/bad_unwind_info.pass.cpp b/libunwind/test/bad_unwind_info.pass.cpp
index b3284e8daed71..95fdb282d4dae 100644
--- a/libunwind/test/bad_unwind_info.pass.cpp
+++ b/libunwind/test/bad_unwind_info.pass.cpp
@@ -77,4 +77,7 @@ extern "C" void stepper() {
   assert(unw_step(&cursor) <= 0);
 }
 
-int main() { bad_unwind_info(); }
+int main(int, char**) {
+  bad_unwind_info();
+  return 0;
+}
diff --git a/libunwind/test/eh_frame_fde_pc_range.pass.cpp b/libunwind/test/eh_frame_fde_pc_range.pass.cpp
index 852612bd9a6e4..c28a2759c5366 100644
--- a/libunwind/test/eh_frame_fde_pc_range.pass.cpp
+++ b/libunwind/test/eh_frame_fde_pc_range.pass.cpp
@@ -21,7 +21,7 @@
 
 // RUN: %{build}
 // RUN: %{objcopy} --dump-section .eh_frame_hdr=%t_ehf_hdr.bin %t.exe
-// RUN: echo -ne '\xFF' | dd of=%t_ehf_hdr.bin bs=1 seek=2 count=2 conv=notrunc status=none 
+// RUN: echo -ne '\xFF' | dd of=%t_ehf_hdr.bin bs=1 seek=2 count=2 conv=notrunc status=none
 // RUN: %{objcopy} --update-section .eh_frame_hdr=%t_ehf_hdr.bin %t.exe
 // RUN: %{exec} %t.exe
 
@@ -53,7 +53,7 @@ void f() {
   assert(fde_fpc == fde_fpc1);
 }
 
-int main() {
+int main(int, char**) {
   f();
   return 0;
 }
diff --git a/libunwind/test/floatregister.pass.cpp b/libunwind/test/floatregister.pass.cpp
index ce4481bdf8287..018b792bd5f1e 100644
--- a/libunwind/test/floatregister.pass.cpp
+++ b/libunwind/test/floatregister.pass.cpp
@@ -52,7 +52,7 @@ __attribute__((noinline)) void foo() {
   _Unwind_Backtrace(frame_handler, NULL);
 }
 
-__attribute__((section("main_func"))) int main() {
+__attribute__((section("main_func"))) int main(int, char **) {
   foo();
   return -2;
 }
diff --git a/libunwind/test/forceunwind.pass.cpp b/libunwind/test/forceunwind.pass.cpp
index 344034e1ea5f5..9e032fc680806 100644
--- a/libunwind/test/forceunwind.pass.cpp
+++ b/libunwind/test/forceunwind.pass.cpp
@@ -72,7 +72,7 @@ __attribute__((noinline)) void foo() {
   _Unwind_ForcedUnwind(e, stop, (void *)&foo);
 }
 
-__attribute__((section("main_func"))) int main() {
+__attribute__((section("main_func"))) int main(int, char **) {
   foo();
   return -2;
 }
diff --git a/libunwind/test/unw_resume.pass.cpp b/libunwind/test/unw_resume.pass.cpp
index 2b7470b5cad0e..17c3e8a4f2296 100644
--- a/libunwind/test/unw_resume.pass.cpp
+++ b/libunwind/test/unw_resume.pass.cpp
@@ -25,7 +25,7 @@ __attribute__((noinline)) void test_unw_resume() {
   unw_resume(&cursor);
 }
 
-int main() {
+int main(int, char**) {
   test_unw_resume();
   return 0;
 }
diff --git a/libunwind/test/unwind_scalable_vectors.pass.cpp b/libunwind/test/unwind_scalable_vectors.pass.cpp
index a5c5947c870fd..57ef4d78244c5 100644
--- a/libunwind/test/unwind_scalable_vectors.pass.cpp
+++ b/libunwind/test/unwind_scalable_vectors.pass.cpp
@@ -34,7 +34,10 @@ __attribute__((noinline)) static void foo() {
   asm volatile("" ::"vr"(v));  // Dummy inline asm to use v.
 }
 
-int main() { foo(); }
+int main(int, char **) {
+  foo();
+  return 0;
+}
 #else
-int main() { return 0; }
+int main(int, char **) { return 0; }
 #endif

Copy link

github-actions bot commented Oct 8, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Contributor

@ojhunt ojhunt left a comment

Choose a reason for hiding this comment

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

LGTM, only question is whether this should be const char**

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++abi libc++abi C++ Runtime Library. Not libc++. libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. libunwind
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants