Index: flang/runtime/CMakeLists.txt =================================================================== --- flang/runtime/CMakeLists.txt +++ flang/runtime/CMakeLists.txt @@ -62,6 +62,38 @@ message(FATAL_ERROR "None of strerror, strerror_r, strerror_s found.") endif() +include(CheckCXXCompilerFlag) +check_cxx_compiler_flag(-fext-numeric-literals SUPPORTS_FEXT_NUMERIC_LITERALS) +check_cxx_compiler_flag(-Wno-error=pedantic SUPPORTS_W_NO_ERROR_PEDANTIC) +if (SUPPORTS_FEXT_NUMERIC_LITERALS AND SUPPORTS_W_NO_ERROR_PEDANTIC) + set(CMAKE_REQUIRED_FLAGS + "${CMAKE_REQUIRED_FLAGS} -Wno-error=pedantic -fext-numeric-literals") + check_cxx_source_compiles( + "#include + int main() { + __float128 x = FLT128_MAX; + return 0; + } + " + HAVE_QUADMATH_H) + + # Even with -fext-numeric-literals, GCC -Wpedantic warns about + # non-standard suffix on floating constant expanded from FLT128_MAX. + # Neither __extension__ nor 'GCC diagnostic ignored "-Wpedantic"' work, + # so usage of FLT128_MAX will cause warnings with -Wpedantic. + # -Werror will turn this warning into an error, so we have to + # override it with -Wno-error=pedantic both here and for the files + # that use FLT128_MAX (e.g. extrema.cpp). + # Also see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87274 + if (HAVE_QUADMATH_H) + set(files_with_quadmath extrema.cpp) + set_source_files_properties(${files_with_quadmath} + PROPERTIES COMPILE_OPTIONS "-Wno-error=pedantic;-fext-numeric-literals") + set_source_files_properties(${files_with_quadmath} + PROPERTIES COMPILE_DEFINITIONS "HAVE_QUADMATH_H") + endif() +endif() + configure_file(config.h.cmake config.h) # include_directories is used here instead of target_include_directories # because add_flang_library creates multiple objects (STATIC/SHARED, OBJECT) Index: flang/runtime/extrema.cpp =================================================================== --- flang/runtime/extrema.cpp +++ flang/runtime/extrema.cpp @@ -19,6 +19,9 @@ #include #include #include +#if HAVE_QUADMATH_H +#include +#endif // HAVE_QUADMATH_H namespace Fortran::runtime { @@ -301,7 +304,8 @@ // MAXVAL and MINVAL -template struct MaxOrMinIdentity { +template +struct MaxOrMinIdentity { using Type = CppTypeFor; static constexpr Type Value() { return IS_MAXVAL ? std::numeric_limits::lowest() @@ -318,6 +322,23 @@ } }; +#if HAVE_QUADMATH_H +// std::numeric_limits<> may not support __float128, +// so use macros defined in quadmath.h (if available). +// +// Note that HAVE_QUADMATH_H implies that __float128 is available, +// but it does not necessarily mean that __float128 is used for REAL(16). +// This specialization must engage only when +// CppTypeFor is __float128. +template +struct MaxOrMinIdentity, __float128>>> { + using Type = CppTypeFor; + static constexpr Type Value() { return IS_MAXVAL ? -FLT128_MAX : FLT128_MAX; } +}; +#endif // HAVE_QUADMATH_H + template class NumericExtremumAccumulator { public: Index: flang/unittests/Runtime/Reduction.cpp =================================================================== --- flang/unittests/Runtime/Reduction.cpp +++ flang/unittests/Runtime/Reduction.cpp @@ -616,3 +616,20 @@ EXPECT_FALSE(RTNAME(DotProductLogical)( *logicalVector2, *logicalVector1, __FILE__, __LINE__)); } + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +TEST(Reductions, ExtremaReal16) { + // The identity value for Min/Maxval for REAL(16) was mistakenly + // set to 0.0. + using ElemType = CppTypeFor; + std::vector shape{3}; + // 1.0 2.0 3.0 + std::vector rawMinData{1.0, 2.0, 3.0}; + auto minArray{MakeArray(shape, rawMinData)}; + EXPECT_EQ(RTNAME(MinvalReal16)(*minArray, __FILE__, __LINE__), 1.0); + // -1.0 -2.0 -3.0 + std::vector rawMaxData{-1.0, -2.0, -3.0}; + auto maxArray{MakeArray(shape, rawMaxData)}; + EXPECT_EQ(RTNAME(MaxvalReal16)(*maxArray, __FILE__, __LINE__), -1.0); +} +#endif // LDBL_MANT_DIG == 113 || HAS_FLOAT128