Bug 117210 - [15 regression] error: 'llabs' is not a member of 'std'; did you mean 'labs'
Summary: [15 regression] error: 'llabs' is not a member of 'std'; did you mean 'labs'
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 15.0
: P3 normal
Target Milestone: 15.0
Assignee: Jonathan Wakely
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-10-18 12:35 UTC by Vedran Miletic
Modified: 2024-12-05 08:20 UTC (History)
7 users (show)

See Also:
Host:
Target: *-*-freebsd
Build:
Known to work:
Known to fail:
Last reconfirmed: 2024-11-18 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vedran Miletic 2024-10-18 12:35:57 UTC
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.
Comment 1 Andrew Pinski 2024-10-18 12:44:08 UTC
Looks to be freebsd specific.
Comment 2 Vedran Miletic 2024-10-18 14:05:32 UTC
Lorenzo, thanks for packaging new versions so regularly. This issue started roughly 2-3 versions ago, any ideas why it could be?
Comment 3 Vedran Miletic 2024-11-17 09:24:37 UTC
FWIW, this issue still exists with:

% g++15 --version
g++15 (FreeBSD Ports Collection) 15.0.0 20241110 (experimental)
Comment 4 Sam James 2024-11-17 09:26:47 UTC
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?
Comment 5 Lorenzo Salvadore 2024-11-17 09:33:20 UTC
(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.
Comment 6 Dimitry Andric 2024-11-17 19:04:40 UTC
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.
Comment 7 Jonathan Wakely 2024-11-18 14:57:41 UTC
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.
Comment 8 Jonathan Wakely 2024-11-18 14:58:30 UTC
Maybe we just need to include sys/cdefs.h in os_defines.h
Comment 9 Jonathan Wakely 2024-11-18 14:59:18 UTC
Does this work?

#include <sys/cdefs.h>
#include <cstdlib>

int main ()
{
        long long a = 5;
        std::llabs(a);
        return 0;
}
Comment 10 Dimitry Andric 2024-11-18 15:04:26 UTC
(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>.
Comment 11 Jonathan Wakely 2024-11-18 15:19:01 UTC
(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
Comment 12 Dimitry Andric 2024-11-19 17:34:38 UTC
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.
Comment 13 Jakub Jelinek 2024-11-19 17:45:28 UTC
(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).
Comment 14 Jonathan Wakely 2024-11-27 14:18:05 UTC
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.
Comment 15 GCC Commits 2024-11-28 10:08:05 UTC
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.
Comment 16 Jonathan Wakely 2024-11-28 10:09:29 UTC
This should be fixed now.
Comment 17 Vedran Miletic 2024-12-05 07:26:37 UTC
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.
Comment 18 Jonathan Wakely 2024-12-05 08:20:43 UTC
Great, thanks for checking it.