GCC compiler and y0 variable

FreeBSD 15.0 comes with GCC 14.2 compiler. This code,
C:
#include<stdio.h>
#include<math.h>
double y0;
int main()
{
    printf("%lf\n",y0);
    return 0;
}
produces an error at compilation time as the variable y0 is declared as global, and y0 is the name of a function (one of the Bessel's functions) declared in math.h. If the variable is declared as local to the main() function, the code compiles without errors. But y0 function, although present in UNIX since late 70s and POSIX compliant, is not conformal with any C standard, so the presented code compiles with, for example,
Code:
gcc -std=c99 file.c -o file
in Linux using the GCC compiler. But in FreeBSD the GCC call with -std=c99 flag also produces the same error as without it. So the question is, why the GCC version packed by FreeBSD does not show the same behavior in this case with -std=c99 as the Linux version?
 
FreeBSD 15.0 comes with GCC 14.2 compiler.
No. FreeBSD comes with LLVM, not GCC. It hasn't used GCC in a very long time.

Code:
dice@maelcum:~ % cc --version
FreeBSD clang version 19.1.7 (https://github.com/llvm/llvm-project.git llvmorg-19.1.7-0-gcd708029e0b2)
Target: x86_64-unknown-freebsd15.0
Thread model: posix
InstalledDir: /usr/bin
dice@maelcum:~ % freebsd-version
15.0-RELEASE
 
y0 is defined in math.h so a clash is normal.
Yes, I know, but in GCC is defined conditionally and when you use the option -std=c89, -std=c99, etc. that definitions are not taken into account as Bessel's function does not belong to the ISO standard of the language. My question is why in the GCC that are in FreeBSD the option -std=c99 does not work for this case while in GCC on Linux does.
 
gcc is not the default in FreeBSD, so it must have been installed as a package.
on your FreeBSD and Linux systems, what is the output of "gcc --version" If they are different versions, that is a hint as to why they behave differently.
You should also compare math.h on both systems to see how "y0" is guarded in each (#ifdef stuff).
Once you get that, manpage on both may tell you what is/is not defined for any given -std setting.
 
Not a programmer, and certainly no C standards expert, but I'm quite sure the definition of __BSD_VISIBLE has something to do with it. It would explain the difference in behavior between Linux and BSD.
Code:
#if __BSD_VISIBLE || __XSI_VISIBLE
double  j0(double);
double  j1(double);
double  jn(int, double);
double  y0(double);
double  y1(double);
double  yn(int, double);

As far as I understood that flag, it's mainly because certain traditional BSD functions are incompatible with POSIX.
 
  • Like
Reactions: mer
Not a programmer, and certainly no C standards expert, but I'm quite sure the definition of __BSD_VISIBLE has something to do with it. It would explain the difference in behavior between Linux and BSD.
Code:
#if __BSD_VISIBLE || __XSI_VISIBLE
double  j0(double);
double  j1(double);
double  jn(int, double);
double  y0(double);
double  y1(double);
double  yn(int, double);

As far as I understood that flag, it's mainly because certain traditional BSD functions are incompatible with POSIX.
Thank you very much for your answer. I've installed in FreeBSD GCC 14.2 via pkg. In addition to clarifying some things for me, your answer has raised some more questions.

When I compile the code in Linux without the -std= option I obviously obtain the error. It not points directly to math.h, but to the file mathcalls.h, which is used by math.h
Code:
hola.c:3:8: error: ‘y0’ redeclared as different kind of symbol
    3 | double y0;
      |        ^~
In file included from /usr/include/features.h:523,
                 from /usr/include/x86_64-linux-gnu/bits/libc-header-start.h:33,
                 from /usr/include/stdio.h:28,
                 from hola.c:1:
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:277:1: note: previous declaration of ‘y0’ with type ‘double(double)’
  277 | __MATHCALL (y0,, (_Mdouble_));
      | ^~~~~~~~~~

The output of GCC in FreeBSD is
Code:
hola.c:3:8: error: 'y0' redeclared as different kind of symbol
    3 | double y0;
      |        ^~
In file included from hola.c:2:
/usr/include/math.h:298:9: note: previous declaration of 'y0' with type 'double(double)'
  298 | double  y0(double);
that points to the file /usr/include/math.h. Inspecting this file I can see in FreeBSD that Bessel's functions are defined on it (as you posted), and the header reads
C:
/*
 * ====================================================
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 *
 * Developed at SunPro, a Sun Microsystems, Inc. business.
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */
so this math.h is not the math.h that comes with GCC. So my confusion is about why invoking GCC in FreeBSD does not mean the use of headers coming with GCC (the results must be the same if both math.h files where written with the same criteria, but it is clear that it isn't the case).

On the other hand, in the header of the file /usr/include/features.h of GCC in Linux (in FreeBSD this file does not exists) we can read
C:
/*
   The `-ansi' switch to the GNU C compiler, and standards conformance
   options such as `-std=c99', define __STRICT_ANSI__.  If none of
   these are defined, or if _DEFAULT_SOURCE is defined, the default is
   to have _POSIX_SOURCE set to one and _POSIX_C_SOURCE set to
   200809L, as well as enabling miscellaneous functions from BSD and
   SVID.  If more than one of these are defined, they accumulate.  For
   example __STRICT_ANSI__, _POSIX_SOURCE and _POSIX_C_SOURCE together
   give you ISO C, 1003.1, and 1003.2, but nothing else.
*/

I'm sure I'm misunderstanding something, but I don't know what it is.
 
Using a meaningful variable name with more than 2 characters will not solve this problem?

Following coding best practices guidelines could never be a bad idea :)
Yes, when you write the code you can follow best practices guidelines (in fact, to follow C99 is a good practice whenever the compiler also follows the standard), but when you need to compile a third party software with thousands of lines it is not that simple.
 
Everyone here will agree that the function in math.h should have been called Bessel_y0; the name is short and the intent is clear. It wasn't done that way, and it's up to us to adapt.

C doesn't have any name space, but we can bypass this by using prefixes or structures. Using static statements can lower confilting names.
 
I don't know C or C++. Could #include help in c. Or namespace in C++. Or is this is only for your program and not for the libraries ...
I have to compile a horrible C source code plenty of global variables, being one of them double y0, which is used all accross several source files hundreds of times. Until now I didn't know that y0 is a function in math.h, and as I'm in Linux and the Makefile provided wih the code uses GCC and the -std=c99 option all works fine. As these days I've installed FreeBSD in VirtualBox I compiled the code also in BSD using GCC and then I obtained the compilation error. Searching for information I found that Bessel's functions in math.h belong to some standards but not to ISO C nor C99 (https://www.johndcook.com/blog/math_h/, https://www.ibm.com/docs/en/zos/3.2.0?topic=functions-y0-y1-yn-bessel-second-kind), so this is the origin of my question about the reason why the FreeBSD's GCC port produces the error although CMD]-std=c99[/CMD] is used.
 
Well as far i understand , bsd and linux , or call it , clang and gcc, might have different understandings of standards.
But hey , isn't Microsoft the standard :)
 
Well as far i understand , bsd and linux , or call it , clang and gcc, might have different understandings of standards.
But hey , isn't Microsoft the standard :)
Yes, at least it is not Microsoft code... Finally I think the difference is not the compiler understanding the standard but the c standard library of each system, glibc in Linux and BSD libc in FreeBSD. I can compile the code with -std=c99 option in Linux using GCC, Clang and also the Portland Group (now in the NVIDIA SKD) compilers. The reason is that all read the math.h from glibc. In FreeBSD both GCC and Clang fails although is -std=c99 because the math.h header file comes from BSD libc
 
It's the feature macro that SirDice mentioned above; you are correct it's not compiler itself. Different functions are visible (by default) on either systems.
You could reproduce the same error on Linux by enabling feature macros by adding #define _GNU_SOURCE in the code you provided. Those yN() functions would be visible then and you'd encounter the same error.
 
Yes, at least it is not Microsoft code... Finally I think the difference is not the compiler understanding the standard but the c standard library of each system, glibc in Linux and BSD libc in FreeBSD. I can compile the code with -std=c99 option in Linux using GCC, Clang and also the Portland Group (now in the NVIDIA SKD) compilers. The reason is that all read the math.h from glibc. In FreeBSD both GCC and Clang fails although is -std=c99 because the math.h header file comes from BSD libc
For c++ you at least got some include in /usr/local/lib/gcc14/include.
So there is not really any include files for c specific to gcc14.
 
Code:
#include <stdio.h>
#undef __BSD_VISIBLE
#undef __XSI_VISIBLE
#include <math.h>

double y0 = 0.0;

int main()
{
    printf("%lf\n", y0);
    return 0;
}

Code:
gcc -fno-builtin l2.c
 
Code:
#include <stdio.h>
#undef __BSD_VISIBLE
#undef __XSI_VISIBLE
#include <math.h>

double y0 = 0.0;

int main()
{
    printf("%lf\n", y0);
    return 0;
}

Code:
gcc -fno-builtin l2.c
Thank you very much, it works. At least in mu installation of FreeBSD 15 with GCC 14.2 and Clang 19.1.7 the -fno-builtin is not necessary in the compilation order.

Maybe, based on https://docs.freebsd.org/en/books/porters-handbook/porting-dads/#porting-versions, the best solution would be
C:
#include<stdio.h>
#include<sys/param.h>
#ifdef __FreeBSD__
#undef __BSD_VISIBLE
#undef __XSI_VISIBLE
#endif
#include<math.h>
double y0;
int main()
{
    printf("%lf\n",y0);
    return 0;
}
 
The error that you describe is just how things should work regarding symbol resolution and scopes. Symbols in inner scopes can hide symbols in outer scopes but you can't have the same symbol more than once at the same scope.

On Linux y0 is in bits/mathcalls.h, protected by

#if defined __USE_MISC || (defined __USE_XOPEN && __MATH_DECLARING_DOUBLE)

I can't explain all of those macros (other than __USE_XOPEN). It looks like GCC adds the __STRICT_ANSI__ define when you use -std=c99.

You can't realy exepect too much standard behaviour when using non-standard extensions. It's up to the libraray vendor as to what they support and how it behaves.
 
Back
Top