The following program: #include <cstdlib> int main () { long long a = 5; std::llabs(a); return 0; } fails to compile with GCC 15: % g++15 --version g++15 (FreeBSD Ports Collection) 15.0.0 20241013 (experimental) Copyright (C) 2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The error is: % g++15 prog.cc foo.cc: In function 'int main()': foo.cc:6:14: error: 'llabs' is not a member of 'std'; did you mean 'labs'? 6 | std::llabs(a); | ^~~~~ | labs GCC 13 and 14 compile the program fine.
Looks to be freebsd specific.
Lorenzo, thanks for packaging new versions so regularly. This issue started roughly 2-3 versions ago, any ideas why it could be?
FWIW, this issue still exists with: % g++15 --version g++15 (FreeBSD Ports Collection) 15.0.0 20241110 (experimental)
I'm not Jonathan but I don't have a particularly useful guess for when this started. Any chance you'd be willing to bisect it?
(In reply to Vedran Miletic from comment #2) > Lorenzo, thanks for packaging new versions so regularly. This issue started > roughly 2-3 versions ago, any ideas why it could be? Thanks for reporting and sorry if I have not replied yet, but I am busy with lots of stuff. I will try to have a look into this as soon as possible. In the meantime, I will also ask for help to another FreeBSD developer: we had some changes in the FreeBSD headers recently enough and we also had a few issues with headers poisoning; since he already dealt with those problems, he might be able to help.
It's conditionalized on _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC in <cstdlib> namespace std { #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC using ::__gnu_cxx::lldiv_t; #endif using ::__gnu_cxx::_Exit; #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC using ::__gnu_cxx::llabs; using ::__gnu_cxx::div; using ::__gnu_cxx::lldiv; #endif using ::__gnu_cxx::atoll; using ::__gnu_cxx::strtof; using ::__gnu_cxx::strtoll; using ::__gnu_cxx::strtoull; using ::__gnu_cxx::strtold; } // namespace std In the FreeBSD port I see in /usr/local/lib/gcc15/include/c++/x86_64-portbld-freebsd15.0/bits/os_defines.h: #define _GLIBCXX_USE_C99_DYNAMIC (!(__ISO_C_VISIBLE >= 1999)) #define _GLIBCXX_USE_C99_LONG_LONG_CHECK 1 #if _GLIBCXX_USE_C99_DYNAMIC || !defined __LONG_LONG_SUPPORTED #define _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC 1 #else #define _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC 0 #endif I think __LONG_LONG_SUPPORTED is supposed to come out of a base system header, /usr/include/sys/cdefs.h, and similar for __ISO_C_VISIBLE. However, this piece of code in FreeBSD's os_defines.h changed not that long ago, in commit r15-3904-ge23e5370d58 for bug 116859: --- a/libstdc++-v3/config/os/bsd/freebsd/os_defines.h +++ b/libstdc++-v3/config/os/bsd/freebsd/os_defines.h @@ -36,8 +36,16 @@ #define _GLIBCXX_USE_C99_CHECK 1 #define _GLIBCXX_USE_C99_DYNAMIC (!(__ISO_C_VISIBLE >= 1999)) #define _GLIBCXX_USE_C99_LONG_LONG_CHECK 1 -#define _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC (_GLIBCXX_USE_C99_DYNAMIC || !defined __LONG_LONG_SUPPORTED) +#if _GLIBCXX_USE_C99_DYNAMIC || !defined __LONG_LONG_SUPPORTED +#define _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC 1 +#else +#define _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC 0 +#endif #define _GLIBCXX_USE_C99_FLOAT_TRANSCENDENTALS_CHECK 1 -#define _GLIBCXX_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC defined _XOPEN_SOURCE +#ifdef _XOPEN_SOURCE +#define _GLIBCXX_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC 1 +#else +#define _GLIBCXX_USE_C99_FLOAT_TRANSCENDENTALS_DYNAMIC 0 +#endif #endif There is a good chance this commit is the reason.
Yes, looks likely. I suspect the problem with Jakub's commit is that it requires __LONG_LONG_SUPPORTED and __ISO_C_VISIBLE to have been defined before os_defines.h is included The original (broken) code was supposed to delay evaluation of those macros until _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC was evaluated.
Maybe we just need to include sys/cdefs.h in os_defines.h
Does this work? #include <sys/cdefs.h> #include <cstdlib> int main () { long long a = 5; std::llabs(a); return 0; }
(In reply to Jonathan Wakely from comment #9) > Does this work? > > #include <sys/cdefs.h> > #include <cstdlib> > > int main () > { > long long a = 5; > std::llabs(a); > return 0; > } Yes, that works. So maybe we were lucky that cdefs.h got transitively included in the past, but not anymore? That said, sys/cdefs.h is really a bit of a FreeBSD implementation detail. It does get included automatically with most of the regular system headers, including <stdlib.h>.
(In reply to Dimitry Andric from comment #10) > Yes, that works. So maybe we were lucky that cdefs.h got transitively > included in the past, but not anymore? No. <cmath> basically does this: #include <bits/c++config.h> // which includes: #include <bits/os_defines.h> // which defines: #define _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC (_GLIBCXX_USE_C99_DYNAMIC || !defined __LONG_LONG_SUPPORTED) # include <math.h> // which includes #include <sys/cdefs.h> // which defines #define __LONG_LONG_SUPPORTED // ... #if ! _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC As I said in comment 7, the old definition of the DYNAMIC macro meant it did not care about the value of __LONG_LONG_SUPPORTED until the DYNAMIC macro was used, which was after <sys/cdefs.h>. So __LONG_LONG_SUPPORTED was defined then. The new definition of the DYNAMIC macro expands the value of __LONG_LONG_SUPPORTED immediately, before cdefs.h has been defined. > That said, sys/cdefs.h is really a bit of a FreeBSD implementation detail. Which is why it should be included in the bsd/freebsd/os_defines.h file, not elsewhere. > It does get included automatically with most of the regular system headers, > including <stdlib.h>. But those aren't included until after <bits/c++config.h> which includes os_defines.h
So, something like this? diff --git a/libstdc++-v3/config/os/bsd/freebsd/os_defines.h b/libstdc++-v3/config/os/bsd/freebsd/os_defines.h index 0d63ae6cec4..e414524dcc2 100644 --- a/libstdc++-v3/config/os/bsd/freebsd/os_defines.h +++ b/libstdc++-v3/config/os/bsd/freebsd/os_defines.h @@ -26,6 +26,9 @@ #ifndef _GLIBCXX_OS_DEFINES #define _GLIBCXX_OS_DEFINES 1 +// For __ISO_C_VISIBLE and __LONG_LONG_SUPPORTED +#include <sys/cdefs.h> + // System-specific #define, typedefs, corrections, etc, go here. This // file will come before all others. I think a similar approach might be needed for NetBSD and/or OpenBSD, btw.
(In reply to Dimitry Andric from comment #12) > So, something like this? > > diff --git a/libstdc++-v3/config/os/bsd/freebsd/os_defines.h > b/libstdc++-v3/config/os/bsd/freebsd/os_defines.h > index 0d63ae6cec4..e414524dcc2 100644 > --- a/libstdc++-v3/config/os/bsd/freebsd/os_defines.h > +++ b/libstdc++-v3/config/os/bsd/freebsd/os_defines.h > @@ -26,6 +26,9 @@ > #ifndef _GLIBCXX_OS_DEFINES > #define _GLIBCXX_OS_DEFINES 1 > > +// For __ISO_C_VISIBLE and __LONG_LONG_SUPPORTED > +#include <sys/cdefs.h> > + > // System-specific #define, typedefs, corrections, etc, go here. This > // file will come before all others. > > > I think a similar approach might be needed for NetBSD and/or OpenBSD, btw. Yes. I think for DragonFly, I don't think NetBSD or OpenBSD had something similar (macros with defined inside of it, which with -Wsystem-headers are now warned about).
Alternatively, we could just open code the conditions from sys/cdefs.h Both FreeBSD and DragonFlyBSD do: #if (__GNUC_PREREQ__(2, 0) && !defined(__STRICT_ANSI__)) || \ __STDC_VERSION__ >= 199901 #define __LONG_LONG_SUPPORTED #endif /* C++11 exposes a load of C99 stuff */ #if defined(__cplusplus) && __cplusplus >= 201103L #define __LONG_LONG_SUPPORTED This seems unlikely to change in future releases of those BSDs, so we could just use the same condition, i.e. !defined(__STRICT_ANSI__) || __cplusplus >= 201103L That would avoid including <sys/cdefs.h>. Although realistically, almost any compilation is going to end up including <sys/cdefs.h> eventually.
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:aa9f12e58ddc2298a253cc6e1343ad7e2eb9bcad commit r15-5744-gaa9f12e58ddc2298a253cc6e1343ad7e2eb9bcad Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Nov 27 14:10:34 2024 +0000 libstdc++: Include <sys/cdefs.h> in os_defines.h for FreeBSD [PR117210] This is needed so that __LONG_LONG_SUPPORTED is defined before we depend on it. libstdc++-v3/ChangeLog: PR libstdc++/117210 * config/os/bsd/dragonfly/os_defines.h: Include <sys/cdefs.h>. * config/os/bsd/freebsd/os_defines.h: Likewise.
This should be fixed now.
Pleased to confirm that % g++15 --version g++15 (FreeBSD Ports Collection) 15.0.0 20241201 (experimental) Copyright (C) 2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. works well.
Great, thanks for checking it.