Fix c++11 <cmath> OSX 10.[45] PPC && 10.[4-6] Intel, GNU g++ 4.6 through 8

Also: <math.h> is for C declarations, while <cmath> is for C++ declarations, so put the correct declarations in the correct header. <cmath> includes <math.h>, so this change should not effect current ports that rely on this legacy header.
This commit is contained in:
Michael Dickens
2019-02-28 19:45:45 -08:00
committed by Ken
parent bc4ea645e7
commit b7c6d3c472
6 changed files with 373 additions and 28 deletions
+26 -3
View File
@@ -1,5 +1,6 @@
# GNU Makefile for MacportsLegacySupport
# Copyright (c) 2010 Chris Jones <jonesc@macports.org>
# Copyright (c) 2019 Michael Dickens <michaelld@macports.org>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -111,6 +112,28 @@ $(TESTPRGS_C): %: %.o $(BUILDDLIBPATH)
$(TESTPRGS_CPP): %: %.o $(BUILDDLIBPATH)
$(CXX) $(TESTLDFLAGS) $< $(TESTLIBS) -o $@
# Special clause for testing the cmath fix: Just need to verify that
# building succeeds or fails, not that the executable runs or what it
# produces. Note that for some reason all Clang compilers tested
# (Apple and MP) successfully compile and link this code regardless of
# the c++ standard chosen, which seems to be a build issue since the
# functions being tested were not introduced until c++11. GCC
# correctly fails the compile and link using c++03 or older, but
# succeeds using c++11 -- as desired.
test_cmath: test/test_cmath.cc $(ALLHEADERS)
$(info 1: testing compiler '$(CXX)' for non-legacy cmath using c++03; the build should fail, regardless of the compiler or OS)
$(info 1: $(CXX) $(CXXFLAGS) -std=c++03 $< -o test/$@_cxx03)
@-$(CXX) -I$(SRCINCDIR) $(CXXFLAGS) -std=c++03 $< -o test/$@_cxx03 &> /dev/null && echo "1: c++03 no legacy cmath build success (test failed)!" || echo "1: c++03 no legacy cmath build failure (test succeeded)!"
$(info 2: testing compiler '$(CXX)' for non-legacy cmath using c++03; the build should fail, regardless of the compiler or OS)
$(info 2: $(CXX) -I$(SRCINCDIR) $(CXXFLAGS) -std=c++03 $< -o test/$@_cxx03)
@-$(CXX) -I$(SRCINCDIR) $(CXXFLAGS) -std=c++03 $< -o test/$@_cxx03 &> /dev/null && echo "2: c++03 legacy cmath build success (test failed)!" || echo "2: c++03 legacy cmath build failure (test succeeded)!"
$(info 3: testing compiler '$(CXX)' for non-legacy cmath using c++11; if the compiler supports this standard, then the build should succeed regardless of OS)
$(info 3: $(CXX) $(CXXFLAGS) -std=c++11 $< -o test/$@_cxx11)
@-$(CXX) $(CXXFLAGS) -std=c++11 $< -o test/$@_cxx11 &> /dev/null && echo "3: c++11 no legacy cmath build success (test failed)!" || echo "3: c++11 no legacy cmath build failure (test succeeded)!"
$(info 4: testing compiler '$(CXX)' for legacy cmath using c++11; if the compiler supports this standard, then the build should succeed regardless of OS)
$(info 4: $(CXX) -I$(SRCINCDIR) $(CXXFLAGS) -std=c++11 $< -o test/$@_cxx11)
@-$(CXX) -I$(SRCINCDIR) $(CXXFLAGS) -std=c++11 $< -o test/$@_cxx11 &> /dev/null && echo "4: c++11 legacy cmath build success (test succeeded)!" || echo "4: c++11 legacy cmath build failure (test failed)!"
$(TESTRUNS): $(TESTRUNPREFIX)%: $(TESTNAMEPREFIX)%
$<
@@ -134,12 +157,12 @@ install-slib: $(BUILDSLIBPATH)
$(MKINSTALLDIRS) $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) $(BUILDSLIBPATH) $(DESTDIR)$(LIBDIR)
test check: $(TESTRUNS)
test check: $(TESTRUNS) test_cmath
clean:
$(RM) $(foreach D,$(SRCDIR) $(TESTDIR),$D/*.o $D/*.d)
$(RM) $(BUILDDLIBPATH) $(BUILDSLIBPATH) $(TESTPRGS)
$(RM) $(BUILDDLIBPATH) $(BUILDSLIBPATH) $(TESTPRGS) test/test_cmath_*
@$(RMDIR) $(BUILDDLIBDIR) $(BUILDSLIBDIR)
.PHONY: all dlib slib clean check test $(TESTRUNS)
.PHONY: all dlib slib clean check test $(TESTRUNS) test_cmath
.PHONY: install install-headers install-lib install-dlib install-slib
+2 -1
View File
@@ -14,7 +14,8 @@ via the legacysupport PortGroup.
Wrapped headers are:
- cmath : Adds declaration of various `long long` methods missing in OSX10.6 and older.
- cmath : Adds the same functions as those provided by the herein math.h, in namespace std:: .
- math.h : Adds declaration of various `long long` methods missing in OSX10.6 and older, GCC 8 and older.
- pthread.h : Adds PTHREAD_RWLOCK_INITIALIZER for OSX10.4
- stdio.h : Adds `getline` and `getdelim` functions missing in OSX10.6 and older.
- stdlib.h : Adds `posix_memalign` functional replacement,
+9
View File
@@ -2,6 +2,7 @@
/*
* Copyright (c) 2010 Chris Jones <jonesc@macports.org>
* Copyright (c) 2018 Ken Cunningham <kencu@macports.org>
* Copyright (c) 2019 Michael Dickens <michaelld@macports.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -81,5 +82,13 @@
/* pthread_rwlock_initializer */
#define __MP_LEGACY_SUPPORT_PTHREAD_RWLOCK__ (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050)
/* c++11 <cmath> PPC 10.[45] and Intel 10.[4-6], GNU g++ 4.6 through 8. */
#if (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070 \
&& defined(__GNUC__) && (__GNUC__ <= 8) \
&& ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))))
#define __MP_LEGACY_SUPPORT_CXX11_CMATH__ 1
#else
#define __MP_LEGACY_SUPPORT_CXX11_CMATH__ 0
#endif
#endif /* _MACPORTS_LEGACYSUPPORTDEFS_H_ */
+76 -24
View File
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
* Copyright (c) 2010 Chris Jones <jonesc@macports.org>
* Copyright (c) 2019 Michael Dickens <michaelld@macports.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -14,31 +14,83 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _MACPORTS_CMATH_H_
#define _MACPORTS_CMATH_H_
/* Include the primary system cmath */
#include_next <cmath>
#ifndef _MACPORTS_CMATH_
#define _MACPORTS_CMATH_
/* MP support header */
/* include MP support header to see if c++11 cmath support is needed */
#include "MacportsLegacySupport.h"
/* llround */
#if __MP_LEGACY_SUPPORT_LLROUND__
#ifdef __cplusplus
extern "C" {
#endif
/* Apparently present in library but header declarations are missing in 10.6 */
extern long long int llrint ( double );
extern long long int llrintf ( float );
extern long long int llround ( double );
extern long long int llroundf ( float );
extern long long int llrintl ( long double );
extern long long int llroundl ( long double );
#ifdef __cplusplus
}
#endif
#if __MP_LEGACY_SUPPORT_CXX11_CMATH__
/*
* NOTE: This has to come -before- the include_next, so that the
* setting is valid for any subsequently included header.
*/
#undef L_GLIBCXX_USE_C99_MATH_TR1
#ifndef _GLIBCXX_USE_C99_MATH_TR1
#define L_GLIBCXX_USE_C99_MATH_TR1 1
/*
* this macro enables c++11 math support in g++. It just needs to be
* defined; not to any particular value; use 1 just because.
*/
#define _GLIBCXX_USE_C99_MATH_TR1 1
#endif
#endif /* _MACPORTS_CMATH_H_ */
/*
* Include our local math.h. NOTE: This has to come -before- the
* include_next for <cmath>, so that the top-level functions are
* all declared before they are referenced.
*/
#include <math.h>
#endif /* __MP_LEGACY_SUPPORT_CXX11_CMATH__ */
/*
* Include the next cmath, which might be from the primary system or
* it might be within GCC's c++ headers; either is OK here.
*/
#include_next <cmath>
#if __MP_LEGACY_SUPPORT_CXX11_CMATH__
#ifdef L_GLIBCXX_USE_C99_MATH_TR1
#undef _GLIBCXX_USE_C99_MATH_TR1
#undef L_GLIBCXX_USE_C99_MATH_TR1
#endif
/*
* this is the same condition that defines the function prototypes in
* the system <math.h>.
*/
#if ( defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L ) || ! defined( __STRICT_ANSI__ ) || ! defined( __GNUC__ )
#else
#ifdef _GLIBCXX_NO_C99_ROUNDING_FUNCS
/* have to define these ourselves because GCC doesn't properly */
#if __cplusplus >= 201103L
#undef llrint
#undef llrintf
#undef llrintl
#undef llround
#undef llroundf
#undef llroundl
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
using ::llrint;
using ::llrintf;
using ::llrintl;
using ::llround;
using ::llroundf;
using ::llroundl;
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif /* __cplusplus >= 201103L */
#endif /* _GLIBCXX_NO_C99_ROUNDING_FUNCS */
#endif /* various */
#endif /* __MP_LEGACY_SUPPORT_CXX11_CMATH__ */
#endif /* _MACPORTS_CMATH_ */
+104
View File
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2010 Chris Jones <jonesc@macports.org>
* Copyright (c) 2019 Michael Dickens <michaelld@macports.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _MACPORTS_MATH_H_
#define _MACPORTS_MATH_H_
/* MP support header */
#include "MacportsLegacySupport.h"
#if __MP_LEGACY_SUPPORT_LLROUND__
/* For definition of __*_DECLS */
#include <sys/cdefs.h>
__BEGIN_DECLS
/*
* These functions are present in the system math library but their
* prototypes might not be declared under some circumstances. Declare
* them here anyway.
*/
/*
* this is the same condition that defines the function prototypes in
* the system <math.h>.
*/
#if ( defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L ) || ! defined( __STRICT_ANSI__ ) || ! defined( __GNUC__ )
#else
extern long long int llrint ( double );
extern long long int llrintf ( float );
extern long long int llrintl ( long double );
extern long long int llround ( double );
extern long long int llroundf ( float );
extern long long int llroundl ( long double );
#endif
__END_DECLS
#endif /* __MP_LEGACY_SUPPORT_LLROUND__ */
/*
* Include the next math.h, which might be from the primary system or
* it might be within GCC's c or c++ (yup!) headers
*/
/*
* If the GCC <math.h> header exists, then tell it: (1) to include the
* next <math.h>, which should be from the system; and (2) to not use
* it's <math.h> yet, because it basically wraps <cmath> and we need
* to keep everything herein focused on just <math.h>. If the user
* wants <cmath>, they should #include that specific header.
*/
/* store prior values for _GLIBCXX_MATH_H and _GLIBCXX_INCLUDE_NEXT_C_HEADERS */
#ifdef L_GLIBCXX_MATH_H
#undef L_GLIBCXX_MATH_H
#endif
#ifdef _GLIBCXX_MATH_H
#define L_GLIBCXX_MATH_H _GLIBCXX_MATH_H
#endif
#define _GLIBCXX_MATH_H 1
#ifdef L_GLIBCXX_INCLUDE_NEXT_C_HEADERS
#undef L_GLIBCXX_INCLUDE_NEXT_C_HEADERS
#endif
#ifdef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
#define L_GLIBCXX_INCLUDE_NEXT_C_HEADERS _GLIBCXX_INCLUDE_NEXT_C_HEADERS
#endif
#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS 1
#include_next <math.h>
/* restore prior values for _GLIBCXX_MATH_H and _GLIBCXX_INCLUDE_NEXT_C_HEADERS */
#undef _GLIBCXX_MATH_H
#ifdef L_GLIBCXX_MATH_H
#define _GLIBCXX_MATH_H L_GLIBCXX_MATH_H
#undef L_GLIBCXX_MATH_H
#endif
#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS
#ifdef L_GLIBCXX_INCLUDE_NEXT_C_HEADERS
#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS L_GLIBCXX_INCLUDE_NEXT_C_HEADERS
#undef L_GLIBCXX_INCLUDE_NEXT_C_HEADERS
#endif
#endif /* _MACPORTS_MATH_H_ */
+156
View File
@@ -0,0 +1,156 @@
#if defined(__cplusplus)
#if __cplusplus == 201707L
#warning "Using STD c++2a (will be c++20)"
#elif __cplusplus == 201703L
#warning "Using STD c++17 or c++1z (will be c++17)"
#elif __cplusplus == 201402L
#warning "Using STD c++14"
#elif __cplusplus == 201103L
#warning "Using STD c++11"
#elif __cplusplus == 199711L
#warning "Using STD c++98 or c++03"
#else
#warning "Unknown C++ standard in use ... this should never happen!"
#endif
#if __cplusplus >= 201103L
#if defined(__clang__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1090)
#warning "Building using some Clang compiler on OSX 10.8 or earlier; this will probably fail due to there being no relevant c++11 headers."
#else
#warning "Using c++11 with a compiler that can correctly support it; this build should succeed correctly."
#endif
#else /* __cplusplus < 201103L, so something older than c++11 */
#if defined(__clang__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1080)
#warning "Building using some Clang compiler using OSX 10.9 or newer; this build will probably succeed incorrectly."
#else
#warning "This build should fail correctly for all compilers."
#endif
#endif /* __cplusplus >= 201103L */
#else /* !defined(__cplusplus) */
#warning "No C++ standard set ... this should never happen!"
#endif /* defined(__cplusplus) */
#include <cmath>
#include <iostream>
#define _STR(A) #A
#define STR(A) _STR(A)
#define DOIT(AAA) std::cout << STR(AAA) << " : " << AAA << std::endl
int main() {
DOIT(std::acosh(0.0));
DOIT(std::acoshf(1.1));
DOIT(std::acoshl(1.1));
DOIT(std::asinh(1.1));
DOIT(std::asinhf(1.1));
DOIT(std::asinhl(1.1));
DOIT(std::atanh(1.1));
DOIT(std::atanhf(1.1));
DOIT(std::atanhl(1.1));
DOIT(std::cbrt(1.1));
DOIT(std::cbrtf(1.1));
DOIT(std::cbrtl(1.1));
DOIT(std::copysign(1.1, 1.1));
DOIT(std::copysignf(1.1, 1.1));
DOIT(std::copysignl(1.1, 1.1));
DOIT(std::erf(1.1));
DOIT(std::erff(1.1));
DOIT(std::erfl(1.1));
DOIT(std::erfc(1.1));
DOIT(std::erfcf(1.1));
DOIT(std::erfcl(1.1));
DOIT(std::exp2(1.1));
DOIT(std::exp2f(1.1));
DOIT(std::exp2l(1.1));
DOIT(std::expm1(1.1));
DOIT(std::expm1f(1.1));
DOIT(std::expm1l(1.1));
DOIT(std::fdim(1.1, 1.1));
DOIT(std::fdimf(1.1, 1.1));
DOIT(std::fdiml(1.1, 1.1));
DOIT(std::fma(1.1, 1.1, 1.1));
DOIT(std::fmaf(1.1, 1.1, 1.1));
DOIT(std::fmal(1.1, 1.1, 1.1));
DOIT(std::fmax(1.1, 1.1));
DOIT(std::fmaxf(1.1, 1.1));
DOIT(std::fmaxl(1.1, 1.1));
DOIT(std::fmin(1.1, 1.1));
DOIT(std::fminf(1.1, 1.1));
DOIT(std::fminl(1.1, 1.1));
DOIT(std::hypot(1.1, 1.1));
DOIT(std::hypotf(1.1, 1.1));
DOIT(std::hypotl(1.1, 1.1));
DOIT(std::ilogb(1.1));
DOIT(std::ilogbf(1.1));
DOIT(std::ilogbl(1.1));
DOIT(std::lgamma(1.1));
DOIT(std::lgammaf(1.1));
DOIT(std::lgammal(1.1));
DOIT(std::llrint(1.1));
DOIT(std::llrintf(1.1));
DOIT(std::llrintl(1.1));
DOIT(std::llround(1.1));
DOIT(std::llroundf(1.1));
DOIT(std::llroundl(1.1));
DOIT(std::log1p(1.1));
DOIT(std::log1pf(1.1));
DOIT(std::log1pl(1.1));
DOIT(std::log2(1.1));
DOIT(std::log2f(1.1));
DOIT(std::log2l(1.1));
DOIT(std::logb(1.1));
DOIT(std::logbf(1.1));
DOIT(std::logbl(1.1));
DOIT(std::lrint(1.1));
DOIT(std::lrintf(1.1));
DOIT(std::lrintl(1.1));
DOIT(std::lround(1.1));
DOIT(std::lroundf(1.1));
DOIT(std::lroundl(1.1));
DOIT(std::nan("1"));
DOIT(std::nanf("1"));
DOIT(std::nanl("1"));
DOIT(std::nearbyint(1.1));
DOIT(std::nearbyintf(1.1));
DOIT(std::nearbyintl(1.1));
DOIT(std::nextafter(1.1, 1.1));
DOIT(std::nextafterf(1.1, 1.1));
DOIT(std::nextafterl(1.1, 1.1));
DOIT(std::nexttoward(1.1, 1.1));
DOIT(std::nexttowardf(1.1, 1.1));
DOIT(std::nexttowardl(1.1, 1.1));
DOIT(std::remainder(1.1, 1.1));
DOIT(std::remainderf(1.1, 1.1));
DOIT(std::remainderl(1.1, 1.1));
int quo;
DOIT(std::remquo(1.1, 1.1, &quo));
DOIT(std::remquof(1.1, 1.1, &quo));
DOIT(std::remquol(1.1, 1.1, &quo));
DOIT(std::rint(1.1));
DOIT(std::rintf(1.1));
DOIT(std::rintl(1.1));
DOIT(std::round(1.1));
DOIT(std::roundf(1.1));
DOIT(std::roundl(1.1));
DOIT(std::scalbln(1.1, 1));
DOIT(std::scalblnf(1.1, 1));
DOIT(std::scalblnl(1.1, 1));
DOIT(std::scalbn(1.1, 1));
DOIT(std::scalbnf(1.1, 1));
DOIT(std::scalbnl(1.1, 1));
DOIT(std::tgamma(1.1));
DOIT(std::tgammaf(1.1));
DOIT(std::tgammal(1.1));
DOIT(std::trunc(1.1));
DOIT(std::truncf(1.1));
DOIT(std::truncl(1.1));
return 0;
}