| Summary: | [15 regression] error: 'llabs' is not a member of 'std'; did you mean 'labs' | ||
|---|---|---|---|
| Product: | gcc | Reporter: | Vedran Miletic <vedran> |
| Component: | libstdc++ | Assignee: | Jonathan Wakely <redi> |
| Status: | RESOLVED FIXED | ||
| Severity: | normal | CC: | andreast, daniel.kruegler, developer, dimitry, gerald, jakub, webrown.cpp |
| Priority: | P3 | ||
| Version: | 15.0 | ||
| Target Milestone: | 15.0 | ||
| Host: | Target: | *-*-freebsd | |
| Build: | Known to work: | ||
| Known to fail: | Last reconfirmed: | 2024-11-18 00:00:00 | |
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. |
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.