https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89855

            Bug ID: 89855
           Summary: Inconsistent global namespace overload sets from
                    #include <cmath>
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: foom at fuhm dot net
  Target Milestone: ---

In the following, I use the function "log" as an example, but this applies to
effectively everything in cmath, and ::abs in cstdlib.

The C standard library <math.h> defines:
  double log(double);

libstdc++ <cmath> includes libc <math.h>, and then does:
  namespace std {
    using ::log;
    float log(float);
    long double log(long double);
    double log(Any-Integral-Type);
  }

libstdc++ <math.h> does:
  #include <cmath>
  using std::log;


This has the unfortunate effect that code which includes <cmath> and uses
global ::log ends up accidentally calling the double overload of log. E.g., a
program like this:
  #include <cmath>
  float foo(float f) { return log(f); }

Granted, the above code is non-portable, and may not even compile on some other
standards-conforming implementation. I do not believe this is a
standards-compliance issue in libstdc++ -- the header <cstdlib> is permitted,
but not required to define ::log.

However, IMO, it's a *QoI* bug that libstdc++ doesn't provide consistent
overload sets. The problem is that the behavior of the above code _very subtly_
changes upon adding or removing an #include which transitively has an "#include
<math.h>" in it. This can cause extremely surprising bugs.

I'd suggest that either #include <cmath> ought to define NO global ::log
function at all (thus, the above program fails to compile), or it should define
the entire overload set for ::log. No partial overload sets.

Since not defining ::log from cmath is effectively impossible, given the
current interfaces between libc and libstdc++, I think the latter is what
should be done. Concretely, that simply means moving all of the global
namespace "using std::log" (etc.) statements from libstdc++'s <math.h> into
libstdc++'s <cmath>.


(I would also suggest that it'd be reasonable for a future C++ standard to
require that. E.g., it could say something like: While <math.h> may or may not
declare functions in ::std::, and <cmath> may or may not declare functions in
::, if they _do_ declare any such name, they must define the complete set of
required overloads, not a subset.)

Reply via email to