Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

M_PI (possible g++/clang++ bug)pu

91 views
Skip to first unread message

Keith Thompson

unread,
Jan 5, 2019, 8:12:20 PM1/5/19
to
Consider the following program:

#include <iostream>
#include <cmath>
int main() {
const int M_PI = 22/7;
std::cout << M_PI << '\n';
}

(Yes, I know that the value of 22/7 is 3, not a good approximation of pi.)

Both g++ 8.2.0 and clang++ 7.0.0 fail to compile this, because M_PI is
defined as a macro in <cmath>:

$ g++ -std=c++17 -pedantic-errors -c c.cpp
In file included from /o/apps/gcc-8.2.0/include/c++/8.2.0/cmath:45,
from c.cpp:2:
c.cpp: In function ‘int main()’:
c.cpp:4:15: error: expected unqualified-id before numeric constant
const int M_PI = 22/7;
^~~~

The library implementation is libc6-dev:amd64 2.27-3ubuntu1.

M_PI is defined by POSIX, not by either ISO C or ISO C++. It's not
a reserved identifier in either language, so it should be available
as a user-defined identifier in conforming C++ code.

Am I correct in thinking that this is a bug in the implementation,
or is there some C++ rule that allows conforming implementations
to reject it?

(For a similar C program, using "-std=c11" causes it to compiler
correctly.)

--
Keith Thompson (The_Other_Keith) k...@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Chris M. Thomasson

unread,
Jan 5, 2019, 8:18:42 PM1/5/19
to
On 1/5/2019 5:12 PM, Keith Thompson wrote:
> Consider the following program:
>
> #include <iostream>
> #include <cmath>
> int main() {
> const int M_PI = 22/7;
> std::cout << M_PI << '\n';
> }
>
> (Yes, I know that the value of 22/7 is 3, not a good approximation of pi.)
>
> Both g++ 8.2.0 and clang++ 7.0.0 fail to compile this, because M_PI is
> defined as a macro in <cmath>:
>
> $ g++ -std=c++17 -pedantic-errors -c c.cpp
> In file included from /o/apps/gcc-8.2.0/include/c++/8.2.0/cmath:45,
> from c.cpp:2:
> c.cpp: In function ‘int main()’:
> c.cpp:4:15: error: expected unqualified-id before numeric constant
> const int M_PI = 22/7;
> ^~~~
>
> The library implementation is libc6-dev:amd64 2.27-3ubuntu1.
>
> M_PI is defined by POSIX, not by either ISO C or ISO C++. It's not
> a reserved identifier in either language, so it should be available
> as a user-defined identifier in conforming C++ code.

Just a thought, is _USE_MATH_DEFINES defied?

Keith Thompson

unread,
Jan 5, 2019, 8:32:17 PM1/5/19
to
"Chris M. Thomasson" <invalid_chr...@invalid.invalid> writes:
> On 1/5/2019 5:12 PM, Keith Thompson wrote:
[...]
>> M_PI is defined by POSIX, not by either ISO C or ISO C++. It's not
>> a reserved identifier in either language, so it should be available
>> as a user-defined identifier in conforming C++ code.
>
> Just a thought, is _USE_MATH_DEFINES defied?

I didn't define it (I showed the entire source program and the
command I used to compile it). Adding an #ifdef (and renaming M_PI)
indicates that _USE_MATH_DEFINES is not defined.

The only occurrence of that identifier I found on my system is in
/usr/include/mysql/my_global.h, which seems to assume that defining
it will make M_PI et all visible. That assumption does not appear
to be correct.

Another data point: including <math.h> rather than <cmath> doesn't
change the behavior.

[...]

Keith Thompson

unread,
Jan 5, 2019, 8:34:43 PM1/5/19
to
Keith Thompson <ks...@mib.org> writes:
> "Chris M. Thomasson" <invalid_chr...@invalid.invalid> writes:
>> On 1/5/2019 5:12 PM, Keith Thompson wrote:
> [...]
>>> M_PI is defined by POSIX, not by either ISO C or ISO C++. It's not
>>> a reserved identifier in either language, so it should be available
>>> as a user-defined identifier in conforming C++ code.
>>
>> Just a thought, is _USE_MATH_DEFINES defied?
>
> I didn't define it (I showed the entire source program and the
> command I used to compile it). Adding an #ifdef (and renaming M_PI)
> indicates that _USE_MATH_DEFINES is not defined.
>
> The only occurrence of that identifier I found on my system is in
> /usr/include/mysql/my_global.h, which seems to assume that defining
> it will make M_PI et all visible. That assumption does not appear
> to be correct.

I think _USE_MATH_DEFINES is specific to Microsoft's implementation.

Chris M. Thomasson

unread,
Jan 5, 2019, 8:35:31 PM1/5/19
to
On 1/5/2019 5:32 PM, Keith Thompson wrote:
> "Chris M. Thomasson" <invalid_chr...@invalid.invalid> writes:
>> On 1/5/2019 5:12 PM, Keith Thompson wrote:
> [...]
>>> M_PI is defined by POSIX, not by either ISO C or ISO C++. It's not
>>> a reserved identifier in either language, so it should be available
>>> as a user-defined identifier in conforming C++ code.
>>
>> Just a thought, is _USE_MATH_DEFINES defied?
>
> I didn't define it (I showed the entire source program and the
> command I used to compile it). Adding an #ifdef (and renaming M_PI)
> indicates that _USE_MATH_DEFINES is not defined.
>
> The only occurrence of that identifier I found on my system is in
> /usr/include/mysql/my_global.h, which seems to assume that defining
> it will make M_PI et all visible. That assumption does not appear
> to be correct.
>
> Another data point: including <math.h> rather than <cmath> doesn't
> change the behavior.

Afaict, M_PI should not be available on non-posix systems.

Chris M. Thomasson

unread,
Jan 5, 2019, 8:37:45 PM1/5/19
to
Fwiw, this kind of reminds me of avoiding the use of the _t postfix when
writing POSIX code in C. It clashes with POSIX's use of _t, like
pthread_mutex_t.

Keith Thompson

unread,
Jan 5, 2019, 9:36:06 PM1/5/19
to
"Chris M. Thomasson" <invalid_chr...@invalid.invalid> writes:
[...]
> Afaict, M_PI should not be available on non-posix systems.

Yes, but that wasn't the question. I'm using a POSIX system (Ubuntu
18.04), but I'm invoking the C++ compiler in a mode that should
conform to ISO C++. (I expect M_PI to be available if I invoke the
compiler in a way that makes POSIX-specific features available.)
I believe that means that the name M_PI should be available for
my use. I'm reasonably certain this is true for C (and gcc and
clang behave that way), but I'm slightly less sure for C++.

James Kuyper

unread,
Jan 5, 2019, 11:13:12 PM1/5/19
to
On 1/5/19 20:12, Keith Thompson wrote:
> Consider the following program:
>
> #include <iostream>
> #include <cmath>
> int main() {
> const int M_PI = 22/7;
> std::cout << M_PI << '\n';
> }
>
> (Yes, I know that the value of 22/7 is 3, not a good approximation of pi.)
>
> Both g++ 8.2.0 and clang++ 7.0.0 fail to compile this, because M_PI is
> defined as a macro in <cmath>:
>
> $ g++ -std=c++17 -pedantic-errors -c c.cpp
> In file included from /o/apps/gcc-8.2.0/include/c++/8.2.0/cmath:45,
> from c.cpp:2:
> c.cpp: In function ‘int main()’:
> c.cpp:4:15: error: expected unqualified-id before numeric constant
> const int M_PI = 22/7;
> ^~~~
>
> The library implementation is libc6-dev:amd64 2.27-3ubuntu1.
>
> M_PI is defined by POSIX, not by either ISO C or ISO C++. It's not
> a reserved identifier in either language, so it should be available
> as a user-defined identifier in conforming C++ code.
>
> Am I correct in thinking that this is a bug in the implementation,

It might be, but it might be solvable by choice of the right command
line options (I have not figured out which ones). If so, it's not
conforming without use of those options.

I used -E and -dD to dump #definitions. Providing a #definition for M_PI
is controlled by __USE_XOPEN, which in turn is controlled by
_XOPEN_SOURCE, which in turn is controlled by _GNU_SOURCE, which is
supposedly set by the command line (I'm not sure which command line
option sets it). Explicitly unsetting it using -U_GNU_SOURCE causes the
#definition of M_PI to be removed, but it causes a lot of other
problems, so that's not the right solution.

Alf P. Steinbach

unread,
Jan 6, 2019, 4:56:33 AM1/6/19
to
On 06.01.2019 02:12, Keith Thompson wrote:
> Consider the following program:
>
> #include <iostream>
> #include <cmath>
> int main() {
> const int M_PI = 22/7;
> std::cout << M_PI << '\n';
> }
>
> (Yes, I know that the value of 22/7 is 3, not a good approximation of pi.)
>
> Both g++ 8.2.0 and clang++ 7.0.0 fail to compile this, because M_PI is
> defined as a macro in <cmath>:
>
> $ g++ -std=c++17 -pedantic-errors -c c.cpp
> In file included from /o/apps/gcc-8.2.0/include/c++/8.2.0/cmath:45,
> from c.cpp:2:
> c.cpp: In function ‘int main()’:
> c.cpp:4:15: error: expected unqualified-id before numeric constant
> const int M_PI = 22/7;
> ^~~~
>
> The library implementation is libc6-dev:amd64 2.27-3ubuntu1.
>
> M_PI is defined by POSIX, not by either ISO C or ISO C++. It's not
> a reserved identifier in either language, so it should be available
> as a user-defined identifier in conforming C++ code.
>
> Am I correct in thinking that this is a bug in the implementation,

Assuming that you haven't defined `_USE_MATH_DEFINED`, then yes, it
should not be defined by default.


> or is there some C++ rule that allows conforming implementations
> to reject it?
>
> (For a similar C program, using "-std=c11" causes it to compiler
> correctly.)

The best course of action is IMO to /not/ all use uppercase names that
clash with Posix macros.

Alternatively you can try defining `__STRICT_ANSI__`.


Cheers & hth.,

- Alf

Keith Thompson

unread,
Jan 6, 2019, 7:00:26 AM1/6/19
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:
> James Kuyper <james...@alumni.caltech.edu> writes:
>>It might be, but it might be solvable by choice of the right command
>>line options (I have not figured out which ones).
>
> Compiles here with g++ 9 if »-std=c++2a« is used.
> Does not compile here if g++ 9 is used with no options.

Hmm. It still fails with "g++ -std=c++2a", using g++ compiled from
source a few weeks ago (revision 5c93472397c, 2018-12-20).

With no options, g++ is non-conforming, so I'm not surprised that it
fails. What about "-std=c++11" or "-std=c++17"? Or it might be a
difference in the library implementation rather than in the compiler.

Keith Thompson

unread,
Jan 6, 2019, 7:15:22 AM1/6/19
to
The best course of action is not to try to use names that are defined
by POSIX. This wasn't something I ran into in real-world code.
But it can be difficult to keep track of which identifiers are
defined by POSIX (or by any number of other secondary standards).

> Alternatively you can try defining `__STRICT_ANSI__`.

That has no effect.

I think the problem is in GNU libc, or in its interaction with g++.
Under Cygwin, which uses a different library implementation, the
problem doesn't occur with g++ (though it does occur with clang++).

I'll submit a bug report.

Chris M. Thomasson

unread,
Jan 6, 2019, 7:32:22 PM1/6/19
to
On 1/6/2019 4:00 AM, Keith Thompson wrote:
> r...@zedat.fu-berlin.de (Stefan Ram) writes:
>> James Kuyper <james...@alumni.caltech.edu> writes:
>>> It might be, but it might be solvable by choice of the right command
>>> line options (I have not figured out which ones).
>>
>> Compiles here with g++ 9 if »-std=c++2a« is used.
>> Does not compile here if g++ 9 is used with no options.
>
> Hmm. It still fails with "g++ -std=c++2a", using g++ compiled from
> source a few weeks ago (revision 5c93472397c, 2018-12-20).
>
> With no options, g++ is non-conforming, so I'm not surprised that it
> fails. What about "-std=c++11" or "-std=c++17"? Or it might be a
> difference in the library implementation rather than in the compiler.
>

Seems like a library implementation problem wrt artificially adding in
M_PI when a user does not want it.

Keith Thompson

unread,
Jan 6, 2019, 8:22:49 PM1/6/19
to

Chris M. Thomasson

unread,
Jan 6, 2019, 8:35:29 PM1/6/19
to
Thank you Keith.

Tim Rentsch

unread,
Feb 28, 2019, 2:56:03 PM2/28/19
to
Keith Thompson <ks...@mib.org> writes:

> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>
>> On 06.01.2019 02:12, Keith Thompson wrote:
>>
>>> Consider the following program:
>>>
>>> #include <iostream>
>>> #include <cmath>
>>> int main() {
>>> const int M_PI = 22/7;
>>> std::cout << M_PI << '\n';
>>> }
>>>
>>> (Yes, I know that the value of 22/7 is 3, not a good approximation of pi.)
>>>
>>> Both g++ 8.2.0 and clang++ 7.0.0 fail to compile this, because M_PI is
>>> defined as a macro in <cmath>:
>>>
>>> $ g++ -std=c++17 -pedantic-errors -c c.cpp
>>> In file included from /o/apps/gcc-8.2.0/include/c++/8.2.0/cmath:45,
>>> from c.cpp:2:
>>> c.cpp: In function ?int main()?:
I think the problem is not in the library headers but in the
translators themselves. After doing a bit of detective work,
I found that these commands

g++ -x c++ -std=c++11 -pedantic -U_GNU_SOURCE m-pi.c -o g++-m-pi
clang-5.0 -x c++ -std=c++11 -pedantic -U_GNU_SOURCE m-pi.c -o clang-m-pi

will compile the source without complaint, and produce
executables that behave as expected, but if the -U_GNU_SOURCE
option is left off then there are compilation errors, like what
you reported. (Which version of C++ standard is used seems not
to matter. The environment is a ubuntu 16.04 distribution.)
0 new messages