Created attachment 24193 [details] Small test case. Hello, I'm not sure it's a real bug (though that example builds fine with gcc 4.5.0) but at least perhaps I'll get help. Consider : #include <stdlib.h> #include <cmath> #include <stdio.h> using namespace std; int main(int argc, char** argv) { double number = 0; if (isnan(number)) { printf("Nan\n"); } return 0; } and build it with : g++ main.cpp -std=c++0x -std=gnu++0x -o test It fails to compile : main.cpp: In function ‘int main(int, char**)’: main.cpp:10:21: error: call of overloaded ‘isnan(double&)’ is ambiguous main.cpp:10:21: note: candidates are: /usr/include/bits/mathcalls.h:235:1: note: int isnan(double) /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/cmath:558:3: note: bool std::isnan(long double) /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/cmath:554:3: note: bool std::isnan(double) /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.0/../../../../include/c++/4.6.0/cmath:550:3: note: bool std::isnan(float) If I deactivate the c++0x support it works. The real issue is that the c++0x standard removes the prohibition on C++ headers declaring C names in the global namespace. The problem here is that math.h is included therefore the declarations are in the global namespace. I'm not really sure how the compiler can solve that but this new "feature" of c++0x seems to be very annoying. I could solve it by not using namespace std but let say the project is huge, it will requires lot of modifications. Basically any time you use using namespace std, you may have conflicts with the underlaying C libraries, it's even more annoying with your own namespace because your functions can conflict with all the stuff in the global namespace put by C libraries and it's very common in a cpp file to use "using namespace foo;" Any suggestions on how I could "workaround" that?
glibc 2.13-5. binutils 2.21-7 Archlinux.
(In reply to comment #0) > > and build it with : g++ main.cpp -std=c++0x -std=gnu++0x -o test There's no point specifying two -std options, only the last one takes effect. > If I deactivate the c++0x support it works. Because in C++98 there is no std::isnan, so you only get the version in the global namespace from <math.h> > The real issue is that the c++0x standard removes the prohibition on C++ > headers declaring C names in the global namespace. The problem here is that > math.h is included therefore the declarations are in the global namespace. I don't think that's the problem, because libstdc++ has always declared the names in the global namespace even though it wasn't valid in C++03 - we haven't changed that for C++0x (all that happened is the standard was relaxed to reflect the reality of actual implementations) > I'm not really sure how the compiler can solve that but this new "feature" of > c++0x seems to be very annoying. I could solve it by not using namespace std > but let say the project is huge, it will requires lot of modifications. > > Basically any time you use using namespace std, you may have conflicts with the > underlaying C libraries, it's even more annoying with your own namespace > because your functions can conflict with all the stuff in the global namespace > put by C libraries and it's very common in a cpp file to use "using namespace > foo;" > > Any suggestions on how I could "workaround" that? Qualify isnan explicitly, by calling either ::isnan or std::isnan
(In reply to comment #2) > (In reply to comment #0) > > > > and build it with : g++ main.cpp -std=c++0x -std=gnu++0x -o test > > There's no point specifying two -std options, only the last one takes effect. > > > If I deactivate the c++0x support it works. > > Because in C++98 there is no std::isnan, so you only get the version in the > global namespace from <math.h> That explain. > > > The real issue is that the c++0x standard removes the prohibition on C++ > > headers declaring C names in the global namespace. The problem here is that > > math.h is included therefore the declarations are in the global namespace. > > I don't think that's the problem, because libstdc++ has always declared the > names in the global namespace even though it wasn't valid in C++03 - we haven't > changed that for C++0x (all that happened is the standard was relaxed to > reflect the reality of actual implementations) > Sorry for my ignorance. > > > I'm not really sure how the compiler can solve that but this new "feature" of > > c++0x seems to be very annoying. I could solve it by not using namespace std > > but let say the project is huge, it will requires lot of modifications. > > > > Basically any time you use using namespace std, you may have conflicts with the > > underlaying C libraries, it's even more annoying with your own namespace > > because your functions can conflict with all the stuff in the global namespace > > put by C libraries and it's very common in a cpp file to use "using namespace > > foo;" > > > > Any suggestions on how I could "workaround" that? > > Qualify isnan explicitly, by calling either ::isnan or std::isnan Well that requires me to modify my entire project, namely WebKit :(. But the more I'm stuck on that issue, the more it seems to be the only solution.
Just wanted to add that the real reason the issue is more subtle now in C++0x mode than it used to be (and still is) in C++03 mode as an extension, is that we now provide the functions in namespace std with the mandated return type, that is bool, whereas in C++03 mode, as an extension, the return type is int, like in C99. Frankly, *given* the usual, well known, limits of our way of dealing with the underlying *.h C headers (included as implementation detail anyway), I don't see any reasonably simple way of solving this family of problems. Actually, anyway, modulo a C++ front-end issue I filed some time ago, I think the <cmath> header isn't *that* far from dispensing with including math.h, the most important blocking issue being the constants FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, which, the last time I asked, Joseph, if I remember correctly, said are very tricky to obtain outside math.h... Anyway, given the different return types in C++0x and C99, the problem would resurface quite unavoidably with: #include <cmath> #include <math.h> using namespace std; of course, if we only fix <cmath> still without fully controlling math.h. Don't hold your breath ;)
Jakub, wrt my Comment #4, would it make sense in your opinion to implement a mechanism requiring cooperation between glibc & libstdc++ similar to the __CORRECT_ISO_CPP_STRING_H_PROTO mechanism you implemented for memchr & co back in 2009-01-30?
I don't think it matters that much whether the return type is int or bool, compared to the inconvenience of having 2 functions that conflict. The constexpr qualifier is nice, but not required by the standard, and not even by gcc which recognizes that extern "C" int isnan(double) is a builtin (note that it doesn't recognize it anymore if you change the return type to bool, that should be fixed). For the same reason (recognized as a builtin), there is no performance advantage to having it inline. So I think: * glibc could change the return type of isnan to bool in C++ (there would be a regression in that ::isnan wouldn't be constexpr and inline until g++ is taught the right prototype) * libstdc++ could import ::isnan in std::, assuming isnan exists. Maybe that requires a configure test. Maybe that test would be rather fragile (depends on feature macros). Maybe that's where this stops being a good idea :-(
*** Bug 68984 has been marked as a duplicate of this bug. ***
*** Bug 60407 has been marked as a duplicate of this bug. ***
There are various ways to hit this issue, some of which mean it can be considered a regression, because the same code compiled with older releases (before we added the C++11 definitions of isinf/isnan) or with -std=gnu++98 (and since the default changed to -std=gnu++14 that means code that worked with the default options now doesn't compile). (In reply to Marc Glisse from comment #6) > * glibc could change the return type of isnan to bool in C++ (there would be > a regression in that ::isnan wouldn't be constexpr and inline until g++ is > taught the right prototype) I think glibc should just not declare those functions in C++ (as Joseph said in Bug 54130 comment 14 they are from Unix98 and not part of C99 anyway, because C99 requires generic macros). > * libstdc++ could import ::isnan in std::, assuming isnan exists. Maybe that > requires a configure test. Maybe that test would be rather fragile (depends > on feature macros). Maybe that's where this stops being a good idea :-( I'm going to take this approach for now, and try to get glibc to change for the future.
It is being tracked by https://sourceware.org/bugzilla/show_bug.cgi?id=19439 and has been fixed by d9b965fa56350d6eea9f7f438a0714c7ffbb183f. It will be included in GLIBC 2.23.
Author: redi Date: Wed Jan 13 16:25:56 2016 New Revision: 232327 URL: https://gcc.gnu.org/viewcvs?rev=232327&root=gcc&view=rev Log: Use ::isinf and ::isnan if libc defines them PR libstdc++/48891 * acinclude.m4 (GLIBCXX_CHECK_MATH11_PROTO): Check for obsolete isinf and isnan functions. * config.h.in: Regenerate. * configure: Regenerate. * include/c_global/cmath (isinf(double), isnan(double)) [_GLIBCXX_HAVE_OBSOLETE_ISINF_ISNAN]: Import via using-directive. * testsuite/26_numerics/headers/cmath/48891.cc: New. Added: trunk/libstdc++-v3/testsuite/26_numerics/headers/cmath/48891.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/acinclude.m4 trunk/libstdc++-v3/config.h.in trunk/libstdc++-v3/configure trunk/libstdc++-v3/include/c_global/cmath
Fixed on trunk.
Author: redi Date: Mon Feb 8 15:22:32 2016 New Revision: 233214 URL: https://gcc.gnu.org/viewcvs?rev=233214&root=gcc&view=rev Log: Enable isinf/isnan checks for all targets PR libstdc++/48891 * acinclude.m4 (GLIBCXX_CHECK_MATH11_PROTO): Enable isinf and isnan checks for all targets except *-*-solaris2.* and ensure we find the libc math.h header not our own. * configure: Regenerate. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/acinclude.m4 trunk/libstdc++-v3/configure