Skip to content

Conversation

yuxuanchen1997
Copy link
Member

An older PR #102036 suggested that LLVM libc declares lgamma_r as noexcept and is incompatible with this redeclaration. However, I recently discovered that glibc also declares the math functions to be noexcept under C++ mode.

This line usually don't cause issues because both the glibc and this file are included as "system headers". According to this godbolt, both GCC and clang ignore the different exception specification between multiple declarations if they are in system headers.

However, this seems not the case for NVCC/EDG, so a fix for this redeclaration is still desirable. This patch proposes that we should declare the function as noexcept under known libc integrations to keep the declared function consistent.

@yuxuanchen1997 yuxuanchen1997 requested a review from a team as a code owner September 2, 2025 22:19
Copy link

github-actions bot commented Sep 2, 2025

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

@yuxuanchen1997 yuxuanchen1997 force-pushed the users/yuxuanchen1997/libcxx-noexcept-on-lgamma-r branch from 6844b07 to ae1da16 Compare September 2, 2025 22:46
@frederick-vs-ja frederick-vs-ja added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Sep 3, 2025
Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

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

I think #153631 (comment) is rather what we should go for.

@llvmbot
Copy link
Member

llvmbot commented Sep 3, 2025

@llvm/pr-subscribers-libcxx

Author: Yuxuan Chen (yuxuanchen1997)

Changes

An older PR #102036 suggested that LLVM libc declares lgamma_r as noexcept and is incompatible with this redeclaration. However, I recently discovered that glibc also declares the math functions to be noexcept under C++ mode.

This line usually don't cause issues because both the glibc and this file are included as "system headers". According to this godbolt, both GCC and clang ignore the different exception specification between multiple declarations if they are in system headers.

However, this seems not the case for NVCC/EDG, so a fix for this redeclaration is still desirable. This patch proposes that we should declare the function as noexcept under known libc integrations to keep the declared function consistent.


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

1 Files Affected:

  • (modified) libcxx/include/__random/binomial_distribution.h (+10-4)
diff --git a/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h
index b4b4340827761..80a910b611adf 100644
--- a/libcxx/include/__random/binomial_distribution.h
+++ b/libcxx/include/__random/binomial_distribution.h
@@ -97,13 +97,19 @@ class binomial_distribution {
   }
 };
 
-// The LLVM C library provides this with conflicting `noexcept` attributes.
-#if !defined(_LIBCPP_MSVCRT_LIKE) && !defined(__LLVM_LIBC__)
-extern "C" double lgamma_r(double, int*);
+// Some libc declares the math functions to be `noexcept`.
+#if _LIBCPP_GLIBC_PREREQ(2, 8) || defined(__LLVM_LIBC__)
+#  define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT
+#else
+#  define _LIBCPP_LGAMMA_R_NOEXCEPT
+#endif
+
+#if !defined(_LIBCPP_MSVCRT_LIKE)
+    extern "C" double lgamma_r(double, int*) _LIBCPP_LGAMMA_R_NOEXCEPT;
 #endif
 
 inline _LIBCPP_HIDE_FROM_ABI double __libcpp_lgamma(double __d) {
-#if defined(_LIBCPP_MSVCRT_LIKE) || defined(__LLVM_LIBC__)
+#if defined(_LIBCPP_MSVCRT_LIKE)
   return lgamma(__d);
 #else
   int __sign;

@yuxuanchen1997
Copy link
Member Author

I think #153631 (comment) is rather what we should go for.

Hi. Would appreciate progress on that work. If no one is working on it, I can also contribute some cycles. In the meantime, this patch can unblock some libc++ CUDA usages.

@yuxuanchen1997 yuxuanchen1997 force-pushed the users/yuxuanchen1997/libcxx-noexcept-on-lgamma-r branch 2 times, most recently from c8a7ec2 to b8be27e Compare September 3, 2025 22:24
@yuxuanchen1997 yuxuanchen1997 force-pushed the users/yuxuanchen1997/libcxx-noexcept-on-lgamma-r branch from b8be27e to a549e73 Compare September 5, 2025 19:26
@yuxuanchen1997 yuxuanchen1997 reopened this Sep 5, 2025
Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

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

I'm fine with this as a workaround until we settle on the right approach in #153631. I think we agree that the status quo doesn't work, so let's land this and then clean it up when we agree on the long term path forward.

@yuxuanchen1997 yuxuanchen1997 merged commit 353d6a9 into main Sep 8, 2025
67 of 79 checks passed
@yuxuanchen1997 yuxuanchen1997 deleted the users/yuxuanchen1997/libcxx-noexcept-on-lgamma-r branch September 8, 2025 21:18
@jhuber6
Copy link
Contributor

jhuber6 commented Sep 8, 2025

This broke the libc version of the build, works if I delete that new macro that was added. I'm confused how this works, since AFAICT a macro won't expand another macro when used in and _NOEXCEPT isn't a standard term as far as I'm aware, so doesn't this just expand to text? Am I missing something?

@philnik777
Copy link
Contributor

This broke the libc version of the build, works if I delete that new macro that was added. I'm confused how this works, since AFAICT a macro won't expand another macro when used in and _NOEXCEPT isn't a standard term as far as I'm aware, so doesn't this just expand to text? Am I missing something?

This should expand normally. Could you provide the diagnostic?

FWIW IMO this has been landed way too eagerly. There hasn't been any more discussion on the other thread so far and this patch has been landed with me opposing it. There was literally no time for me to respond. I'm not a huge fan of changing things without any sort of CI testing for the configuration that is "fixed". OTOH this would have been caught if we had LLVM libc CI coverage, so please make sure to provide that ASAP.

@jhuber6
Copy link
Contributor

jhuber6 commented Sep 9, 2025

This broke the libc version of the build, works if I delete that new macro that was added. I'm confused how this works, since AFAICT a macro won't expand another macro when used in and _NOEXCEPT isn't a standard term as far as I'm aware, so doesn't this just expand to text? Am I missing something?

This should expand normally. Could you provide the diagnostic?

FWIW IMO this has been landed way too eagerly. There hasn't been any more discussion on the other thread so far and this patch has been landed with me opposing it. There was literally no time for me to respond. I'm not a huge fan of changing things without any sort of CI testing for the configuration that is "fixed". OTOH this would have been caught if we had LLVM libc CI coverage, so please make sure to provide that ASAP.

Yeah, I need to get one of the builders updated so it actually hits this path when building at least.

#if defined(_LIBCPP_GLIBC_PREREQ)
# if _LIBCPP_GLIBC_PREREQ(2, 8)
# define _LIBCPP_LGAMMA_R_NOEXCEPT _NOEXCEPT
# endif
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this need an #else? Else the macro isn't defined if the inner #if here isn't true, right?

We're getting this on our bots, I'm guessing due to this:

[187/130551] CXX android_clang_arm/obj/third_party/abseil-cpp/absl/strings/cordz_functions/cordz_functions.o
../../third_party/llvm-build/Release+Asserts/bin/clang++ -MMD -MF android_clang_arm/obj/third_party/abseil-cpp/absl/strings/cordz_functions/co...(too long)
In file included from ../../third_party/abseil-cpp/absl/strings/internal/cordz_functions.cc:20:
In file included from ../../third_party/libc++/src/include/random:1685:
../../third_party/libc++/src/include/__random/binomial_distribution.h:112:42: error: expected function body after function declarator
  112 | extern "C" double lgamma_r(double, int*) _LIBCPP_LGAMMA_R_NOEXCEPT;
      |                                          ^
1 error generated.

Copy link
Contributor

@jhuber6 jhuber6 Sep 9, 2025

Choose a reason for hiding this comment

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

Same thing I'm seeing

Copy link
Contributor

Choose a reason for hiding this comment

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

#157610 added it. Thanks!

@nico
Copy link
Contributor

nico commented Sep 9, 2025

We're also getting build errors on fuchsia with this:

[282/101447] CXX obj/third_party/abseil-cpp/absl/strings/cordz_functions/cordz_functions.o
../../third_party/llvm-build/Release+Asserts/bin/clang++ -MMD -MF obj/third_party/abseil-cpp/absl/strings/cordz_functions/cordz_functions.o.d ...(too long)
In file included from ../../third_party/abseil-cpp/absl/strings/internal/cordz_functions.cc:20:
In file included from ../../third_party/libc++/src/include/random:1685:
../../third_party/libc++/src/include/__random/binomial_distribution.h:114:19: error: exception specification in declaration does not match previous declaration
  114 | extern "C" double lgamma_r(double, int*) _LIBCPP_LGAMMA_R_NOEXCEPT;
      |                   ^
../../third_party/fuchsia-sdk/sdk/obj/x64-api-28/sysroot/include/math.h:398:8: note: previous declaration is here
  398 | double lgamma_r(double, int*);
      |        ^
1 error generated.

@nico
Copy link
Contributor

nico commented Sep 9, 2025

@petrhosek Do you know what this should check for on Fuchsia?

@nico
Copy link
Contributor

nico commented Sep 9, 2025

https://llvm.org/devmtg/2021-11/slides/2021-BuildinganOperatingSystemfromScratchwithLLVM.pdf says "We are evolving our C library and incrementally replacing existing parts with LLVM libc counterparts". I suppose that means we're going down the __LLVM_LIBC__ branch.

libc headers originally didn't have noexcept in math.h, see LHS of https://reviews.llvm.org/D76723 which moved to a first header generation script. That script learned to write noexcept in https://reviews.llvm.org/D141095 in early 2023. The Fuchsia SDK seems to ship headers that don't have that yet. (Or it doesn't use LLVM libc's math.h header at all, but uses enough of it that LLVM_LIBC ends up being set.)

(That header generation script was then later replaced by a different header generation script, which seems to have printed NOEXCEPT from the start, and which is the mechanism that's currently in use.)

@nico
Copy link
Contributor

nico commented Sep 9, 2025

Made #157710 for now.

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

Successfully merging this pull request may close these issues.

7 participants